├── LICENSE ├── LICENSES └── Apache-2.0.txt ├── README.md ├── REUSE.toml ├── application_management ├── Privileges2_manifest.json ├── README.md └── example_profiles │ ├── Example_EnforcePrivileges.mobileconfig │ ├── Example_ExpirationInterval.mobileconfig │ ├── Example_ExpirationIntervalMax.mobileconfig │ ├── Example_LimitToGroup.mobileconfig │ ├── Example_LimitToUser.mobileconfig │ ├── Example_ReasonRequired.mobileconfig │ ├── Example_RemoteLogging.mobileconfig │ └── Example_RequireAuthentication.mobileconfig ├── readme_images ├── CommandLine.png ├── DemoGIF.gif ├── DemoGIFviaDock.gif ├── DockIconCountDown 1.png ├── IllustrationAppComponents.png ├── ManagedDockIcons.png ├── PrivilegesGranted.jpg ├── PrivilegesRevoked.png ├── PrivilegesToogleViaDock.png ├── RequestPrivilegesWindow.png ├── RevertPrivilegesWindow.png ├── RunAppWhenPrivilegeChange.gif ├── UninstallationWindow.png ├── console_show_privileges_process.png ├── console_show_privileges_process_filtered_for_admin.png ├── github banner new.png ├── locked.png ├── locked_managed.png ├── log_show_privileges_process.png ├── log_show_privileges_process_filtered_for_admin.png ├── renewal_custom.png ├── settings_general.png ├── settings_managed.png ├── settings_privileges.png ├── unlocked.png └── unlocked_managed.png └── source ├── Privileges.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── .DS_Store │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── WorkspaceSettings.xcsettings └── xcshareddata │ ├── .DS_Store │ └── xcschemes │ ├── Privileges Beta.xcscheme │ └── Privileges.xcscheme ├── Privileges ├── AppDelegate.h ├── AppDelegate.m ├── AppleScript sample.scpt ├── Base.lproj │ └── Main.storyboard ├── Beta-Info.plist ├── Beta-InfoPlist.xcstrings ├── Credits.rtf ├── Localizable.xcstrings ├── MTReasonAccessory.xib ├── Privileges-ParentConstraint.coderequirement ├── Privileges-SelfConstraint.coderequirement ├── Privileges.entitlements ├── Privileges.mobileconfig ├── Release-Info.plist ├── Release-InfoPlist.xcstrings ├── View Controllers │ ├── MTReasonAccessoryController.h │ ├── MTReasonAccessoryController.m │ ├── MTSettingsGeneralController.h │ ├── MTSettingsGeneralController.m │ ├── MTSettingsPrivilegesController.h │ ├── MTSettingsPrivilegesController.m │ ├── MTTabViewController.h │ └── MTTabViewController.m ├── corp.sap.privileges.agent.plist ├── corp.sap.privileges.daemon.plist ├── corp.sap.privileges.watcher.plist ├── main.m └── mul.lproj │ └── Main.xcstrings ├── PrivilegesAgent ├── AppDelegate.h ├── AppDelegate.m ├── Classes │ ├── MTClientCertificate.h │ ├── MTClientCertificate.m │ ├── MTDaemonConnection.h │ ├── MTDaemonConnection.m │ ├── MTLocalNotification.h │ ├── MTLocalNotification.m │ ├── MTPrivilegeExpirationCommand.h │ ├── MTPrivilegeExpirationCommand.m │ ├── MTPrivilegeStatusCommand.h │ ├── MTPrivilegeStatusCommand.m │ ├── MTStatusItemMenu.h │ ├── MTStatusItemMenu.m │ ├── MTSyslogMessage.h │ ├── MTSyslogMessage.m │ ├── MTSyslogMessageStructuredData.h │ ├── MTSyslogMessageStructuredData.m │ ├── MTWebhook.h │ └── MTWebhook.m ├── Info.plist ├── InfoPlist.xcstrings ├── Localizable.xcstrings ├── Main.storyboard ├── PrivilegesAgent-ParentConstraint.coderequirement ├── PrivilegesAgent-SelfConstraint.coderequirement ├── PrivilegesAgent.entitlements ├── PrivilegesAgent.sdef ├── PrivilegesAgentProtocol.h ├── StatusItem.xcassets │ ├── Contents.json │ ├── locked.imageset │ │ ├── Contents.json │ │ ├── locked-16.png │ │ └── locked-32.png │ ├── locked_managed.imageset │ │ ├── Contents.json │ │ ├── locked_managed-16.png │ │ └── locked_managed-32.png │ ├── unlocked.imageset │ │ ├── Contents.json │ │ ├── unlocked-16.png │ │ └── unlocked-32.png │ └── unlocked_managed.imageset │ │ ├── Contents.json │ │ ├── unlocked_managed-16.png │ │ └── unlocked_managed-32.png └── main.m ├── PrivilegesCLI ├── Classes │ ├── MTProcessInfo.h │ └── MTProcessInfo.m ├── PrivilegesCLI-Info.plist ├── PrivilegesCLI.entitlements └── main.m ├── PrivilegesDaemon ├── Classes │ ├── MTPrivilegesDaemon.h │ └── MTPrivilegesDaemon.m ├── PrivilegesDaemon-Info.plist ├── PrivilegesDaemon-ParentConstraint.coderequirement ├── PrivilegesDaemon-SelfConstraint.coderequirement ├── PrivilegesDaemonProtocol.h └── main.m ├── PrivilegesTile ├── AppIcons-Beta.xcassets │ ├── Contents.json │ ├── locked.imageset │ │ ├── Contents.json │ │ └── locked.png │ ├── locked_managed.imageset │ │ ├── Contents.json │ │ └── locked_managed.png │ ├── unlocked.imageset │ │ ├── Contents.json │ │ └── unlocked.png │ └── unlocked_managed.imageset │ │ ├── Contents.json │ │ └── unlocked_managed.png ├── AppIcons.xcassets │ ├── Contents.json │ ├── locked.imageset │ │ ├── Contents.json │ │ └── locked.png │ ├── locked_managed.imageset │ │ ├── Contents.json │ │ └── locked_managed.png │ ├── unlocked.imageset │ │ ├── Contents.json │ │ └── unlocked.png │ └── unlocked_managed.imageset │ │ ├── Contents.json │ │ └── unlocked_managed.png └── Classes │ ├── PrivilegesTile.h │ └── PrivilegesTile.m ├── PrivilegesWatcher ├── PrivilegesWatcher-Info.plist ├── PrivilegesWatcher-ParentConstraint.coderequirement ├── PrivilegesWatcher-SelfConstraint.coderequirement └── main.m ├── PrivilegesXPC ├── Classes │ ├── PrivilegesXPC.h │ └── PrivilegesXPC.m ├── Info.plist ├── InfoPlist.xcstrings ├── PrivilegesXPC-ParentConstraint.coderequirement ├── PrivilegesXPC-ResponsibleConstraint.coderequirement ├── PrivilegesXPC.entitlements ├── PrivilegesXPCProtocol.h └── main.m └── Shared ├── Assets.xcassets ├── AccentColor.colorset │ └── Contents.json ├── AppIcon-Beta.appiconset │ ├── AppIcon-Beta-1024.png │ ├── AppIcon-Beta-128.png │ ├── AppIcon-Beta-16.png │ ├── AppIcon-Beta-256.png │ ├── AppIcon-Beta-32.png │ ├── AppIcon-Beta-512.png │ ├── AppIcon-Beta-64.png │ └── Contents.json ├── AppIcon.appiconset │ ├── AppIcon-1024.png │ ├── AppIcon-128.png │ ├── AppIcon-16.png │ ├── AppIcon-256.png │ ├── AppIcon-32.png │ ├── AppIcon-512.png │ ├── AppIcon-64.png │ └── Contents.json └── Contents.json ├── Classes ├── MTAgentConnection.h ├── MTAgentConnection.m ├── MTCodeSigning.h ├── MTCodeSigning.m ├── MTIdentity.h ├── MTIdentity.m ├── MTPrivileges.h ├── MTPrivileges.m ├── MTPrivilegesUser.h ├── MTPrivilegesUser.m ├── MTSystemInfo.h └── MTSystemInfo.m ├── Constants.h └── LocalizableMenu.xcstrings /README.md: -------------------------------------------------------------------------------- 1 | ![](https://github.com/SAP/macOS-enterprise-privileges/blob/main/readme_images/github%20banner%20new.png) 2 | 3 |
4 | 5 | # Privileges 6 | 7 | [![REUSE status](https://api.reuse.software/badge/github.com/SAP/macOS-enterprise-privileges)](https://api.reuse.software/info/github.com/SAP/macOS-enterprise-privileges) 8 | 9 | _Privileges_ is an application for macOS which allows users to work as a standard user for day-to-day tasks, by providing a quick and easy way to request administrator rights. Users can set a timeframe in the application’s settings to perform specific tasks, such as installing or removing an application. To request admin rights, simply click on the _Privileges_ icon in your Dock. 10 | 11 | Working as standard user instead of an administrator adds another layer of security to your Mac and is considered a security best practice. We believe all users, including all developers, can benefit from using _Privileges_. 12 | 13 | **Privileges supports the following macOS versions:** 14 | 15 | * macOS 15.x 16 | * macOS 14.x 17 | * macOS 13.x (*) 18 | * macOS 12.x 19 | * macOS 11.x 20 | 21 |
22 | 23 | 24 | >[!NOTE] 25 | >It seems that macOS 13 erroneously reports a launch constraint violation and terminates the appliction immediately. Therefore starting with version 2.2, we'll provide two different versions of the application. One with launch constraints and one whithout. Nevertheless, we recommend using the version with launch constraints whenever possible. 26 |
27 | 28 | # Features 29 | 30 | 🛠️ Easy install 31 | 32 | :rocket: Perfect for day-to-day use 33 | 34 | :alarm_clock: Turn on admin rights anytime 35 | 36 | :closed_lock_with_key: Enjoy standard user security 37 | 38 | :fire: Command line use supported 39 | 40 |
41 | 42 | ## New Privileges 2 features 🔥 43 | 44 | 📦 Installer package 45 | 46 | ⛔️ Revoke admin rights at login 47 | 48 | ⏳ Unified expiration interval for administrator privileges 49 | 50 | 🔁 Renew expiring administrator privileges 51 | 52 | 🪪 Smart card support 53 | 54 | ▶️ Run actions on privilege change 55 | 56 | 🔒 Status item 57 | 58 | 👆 Command line tool now supports Touch ID 59 | 60 | ⚙️ AppleScript support 61 | 62 | 🪝 Webhooks 63 | 64 | 🔠 Localized in 41 languages 65 | 66 |
67 | 68 | # Demo 69 | 70 | ⚡️ Have a look at how quick and easy you can request admin rights 71 | 72 | ![](https://github.com/SAP/macOS-enterprise-privileges/blob/main/readme_images/DemoGIF.gif) 73 | 74 |
75 | 76 | # Application Management 77 | As of _Privileges_ 1.5.0, it is possible to manage settings for _Privileges_ or the _PrivilegesCLI_ command line tool using a macOS configuration profile. [For details, please click here](https://github.com/SAP/macOS-enterprise-privileges/wiki/Managing-Privileges). 78 | 79 |
80 | 81 | # Articles 82 | 83 | See who's talking about _Privileges_… 84 | 85 | 2025 86 | * [Leveling Up - Managing admin rights in the enterprise - Rich Trouton's session at MacAD.UK 2025](https://youtu.be/JSnCdmV_N5U) 87 | * [9To5Mac: Privileges 2.1 continues to be one of the must-have macOS apps in the enterprise](https://9to5mac.com/2025/03/15/privileges-2-1-continues-to-be-one-of-the-must-have-macos-apps-in-the-enterprise/) 88 | * [Caschys Blog: Privileges 2.3.0: Mehr Sicherheit und Kontrolle für Mac-Admins (German language)](https://stadt-bremerhaven.de/privileges-2-3-0-mehr-sicherheit-und-kontrolle-fuer-mac-admins/) 89 | 90 | 2022 91 | * [Mac & i: SAP-Werkzeug erleichtert Arbeit als Standardnutzer (German language)](https://www.heise.de/-7192631) 92 | * [ifun.de: Privileges.app von SAP: Nur noch auf Zuruf zum Admin (German language)](https://www.ifun.de/privileges-app-von-sap-nur-noch-auf-zuruf-zum-admin-191491/) 93 | * [Leveling Up - Rich Trouton's session at MacSysAdmin 2022](https://docs.macsysadmin.se/2022/video/day1session2.mp4) 94 | * [The Great Debate: Admin or Standard Users? - A talk hosted by Kandji](https://youtu.be/LCj59EIKFDg) 95 | 96 | 2019 97 | * [9To5Mac: Privileges for macOS is the open source tool that all Apple IT departments need](https://9to5mac.com/2019/11/16/privileges-app-for-macos/) 98 | 99 |
100 | 101 | # Documentation 102 | 103 | 📚 If you want to learn more about _Privileges_ features, make sure to take a look at our [wiki](https://github.com/SAP/macOS-enterprise-privileges/wiki) or the links below: 104 | 105 | * [Installation](https://github.com/SAP/macOS-enterprise-privileges/wiki/Installation) 106 | * [Uninstallation](https://github.com/SAP/macOS-enterprise-privileges/wiki/Uninstallation) 107 | * [Using Privileges](https://github.com/SAP/macOS-enterprise-privileges/wiki/Using-Privileges) 108 | * [Managing Privileges](https://github.com/SAP/macOS-enterprise-privileges/wiki/Managing-Privileges) 109 | * [Frequently Asked Questions](https://github.com/SAP/macOS-enterprise-privileges/wiki/Frequently-Asked-Questions) 110 | 111 |
112 | 113 | # License 114 | 115 | Copyright (c) 2018-2025 SAP SE or an SAP affiliate company and macOS-enterprise-privileges contributors. Please see our [LICENSE](LICENSE) for copyright and license information. Detailed information including third-party components and their licensing/copyright information is available [via the REUSE tool](https://api.reuse.software/info/github.com/SAP/macOS-enterprise-privileges). 116 | 117 |
118 | 119 | # Security 120 | 121 | Found a security-related issue or vulnerability and want to notify us? [Please see here for how to report it](https://github.com/SAP/macOS-enterprise-privileges/security/policy). 122 | 123 |
124 | 125 | # Support 126 | 127 | This project is 'as-is' with no support, no changes being made. You are welcome to make changes to improve it but we are not available for questions or support of any kind. 128 | -------------------------------------------------------------------------------- /REUSE.toml: -------------------------------------------------------------------------------- 1 | version = 1 2 | SPDX-PackageName = "macOS-enterprise-privileges" 3 | SPDX-PackageDownloadLocation = "https://github.com/SAP/macOS-enterprise-privileges" 4 | SPDX-PackageComment = "The code in this project may include calls to APIs (“API Calls”) of\n SAP or third-party products or services developed outside of this project\n (“External Products”).\n “APIs” means application programming interfaces, as well as their respective\n specifications and implementing code that allows software to communicate with\n other software.\n API Calls to External Products are not licensed under the open source license\n that governs this project. The use of such API Calls and related External\n Products are subject to applicable additional agreements with the relevant\n provider of the External Products. In no event shall the open source license\n that governs this project grant any rights in or to any External Products,or\n alter, expand or supersede any terms of the applicable additional agreements.\n If you have a valid license agreement with SAP for the use of a particular SAP\n External Product, then you may make use of any API Calls included in this\n project’s code for that SAP External Product, subject to the terms of such\n license agreement. If you do not have a valid license agreement for the use of\n a particular SAP External Product, then you may only make use of any API Calls\n in this project for that SAP External Product for your internal, non-productive\n and non-commercial test and evaluation of such API Calls. Nothing herein grants\n you any rights to use or access any SAP External Product, or provide any third\n parties the right to use of access any SAP External Product, through API Calls." 5 | 6 | [[annotations]] 7 | path = "**" 8 | precedence = "aggregate" 9 | SPDX-FileCopyrightText = "2018-2025 SAP SE or an SAP affiliate company and macOS-enterprise-privileges contributors" 10 | SPDX-License-Identifier = "Apache-2.0" 11 | -------------------------------------------------------------------------------- /application_management/README.md: -------------------------------------------------------------------------------- 1 | ![PrivilegesBanner](https://github.com/SAP/macOS-enterprise-privileges/blob/main/readme_images/privileges_banner.gif) 2 | 3 | # Managing Privileges 4 | 5 | For documentation on managing Privileges using configuration profiles, please see the [Managing Privileges](https://github.com/SAP/macOS-enterprise-privileges/wiki/Managing-Privileges) page in our wiki. 6 | -------------------------------------------------------------------------------- /application_management/example_profiles/Example_EnforcePrivileges.mobileconfig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PayloadContent 6 | 7 | 8 | PayloadContent 9 | 10 | corp.sap.privileges 11 | 12 | Forced 13 | 14 | 15 | mcx_preference_settings 16 | 17 | 27 | EnforcePrivileges 28 | admin 29 | 30 | 31 | 32 | 33 | 34 | PayloadDescription 35 | 36 | PayloadDisplayName 37 | Privileges configuration 38 | PayloadEnabled 39 | 40 | PayloadIdentifier 41 | com.apple.ManagedClient.preferences.3F98C2D8-E845-4F59-B447-16AEA78FB584 42 | PayloadOrganization 43 | SAP SE 44 | PayloadType 45 | com.apple.ManagedClient.preferences 46 | PayloadUUID 47 | 3F98C2D8-E845-4F59-B447-16AEA78FB584 48 | PayloadVersion 49 | 1 50 | 51 | 52 | PayloadDescription 53 | Configures the Privileges app. 54 | PayloadDisplayName 55 | Privileges configuration 56 | PayloadEnabled 57 | 58 | PayloadIdentifier 59 | 5790E5B5-A81D-4E4F-9AB6-6F573CC399DD 60 | PayloadOrganization 61 | SAP SE 62 | PayloadRemovalDisallowed 63 | 64 | PayloadScope 65 | System 66 | PayloadType 67 | Configuration 68 | PayloadUUID 69 | 19BF1861-0134-4BC2-9C83-5E4F2FA96BAE 70 | PayloadVersion 71 | 1 72 | 73 | 74 | -------------------------------------------------------------------------------- /application_management/example_profiles/Example_ExpirationInterval.mobileconfig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PayloadContent 6 | 7 | 8 | PayloadContent 9 | 10 | corp.sap.privileges 11 | 12 | Forced 13 | 14 | 15 | mcx_preference_settings 16 | 17 | 25 | ExpirationInterval 26 | 15 27 | 28 | 29 | 30 | 31 | 32 | PayloadDescription 33 | 34 | PayloadDisplayName 35 | Privileges configuration 36 | PayloadEnabled 37 | 38 | PayloadIdentifier 39 | com.apple.ManagedClient.preferences.AEC544EE-591D-4834-900E-4C94858E7871 40 | PayloadOrganization 41 | SAP SE 42 | PayloadType 43 | com.apple.ManagedClient.preferences 44 | PayloadUUID 45 | AEC544EE-591D-4834-900E-4C94858E7871 46 | PayloadVersion 47 | 1 48 | 49 | 50 | PayloadDescription 51 | Configures the Privileges app. 52 | PayloadDisplayName 53 | Privileges configuration 54 | PayloadEnabled 55 | 56 | PayloadIdentifier 57 | 82A2ED21-27DA-428E-8516-446A52169C71 58 | PayloadOrganization 59 | SAP SE 60 | PayloadRemovalDisallowed 61 | 62 | PayloadScope 63 | System 64 | PayloadType 65 | Configuration 66 | PayloadUUID 67 | C2F39834-001F-4930-AC7D-E5BA0DE82529 68 | PayloadVersion 69 | 1 70 | 71 | 72 | -------------------------------------------------------------------------------- /application_management/example_profiles/Example_ExpirationIntervalMax.mobileconfig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PayloadContent 6 | 7 | 8 | PayloadContent 9 | 10 | corp.sap.privileges 11 | 12 | Forced 13 | 14 | 15 | mcx_preference_settings 16 | 17 | 31 | ExpirationIntervalMax 32 | 20 33 | 34 | 35 | 36 | 37 | 38 | PayloadDescription 39 | 40 | PayloadDisplayName 41 | Privileges configuration 42 | PayloadEnabled 43 | 44 | PayloadIdentifier 45 | com.apple.ManagedClient.preferences.8436814F-858D-4875-8552-4263D70478E2 46 | PayloadOrganization 47 | SAP SE 48 | PayloadType 49 | com.apple.ManagedClient.preferences 50 | PayloadUUID 51 | 8436814F-858D-4875-8552-4263D70478E2 52 | PayloadVersion 53 | 1 54 | 55 | 56 | PayloadDescription 57 | Configures the Privileges app. 58 | PayloadDisplayName 59 | Privileges configuration 60 | PayloadEnabled 61 | 62 | PayloadIdentifier 63 | E9DDB703-8D19-40AA-B01D-B6D778E8253D 64 | PayloadOrganization 65 | SAP SE 66 | PayloadRemovalDisallowed 67 | 68 | PayloadScope 69 | System 70 | PayloadType 71 | Configuration 72 | PayloadUUID 73 | C2F39834-001F-4930-AC7D-E5BA0DE82529 74 | PayloadVersion 75 | 1 76 | 77 | 78 | -------------------------------------------------------------------------------- /application_management/example_profiles/Example_LimitToGroup.mobileconfig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PayloadContent 6 | 7 | 8 | PayloadContent 9 | 10 | corp.sap.privileges 11 | 12 | Forced 13 | 14 | 15 | mcx_preference_settings 16 | 17 | 23 | LimitToGroup 24 | 25 | group_name_goes_here 26 | another_group_name_goes_here 27 | 28 | 29 | 30 | 31 | 32 | 33 | PayloadDescription 34 | 35 | PayloadDisplayName 36 | Privileges configuration 37 | PayloadEnabled 38 | 39 | PayloadIdentifier 40 | com.apple.ManagedClient.preferences.36132147-235E-4663-ADA8-2664C67C4DD2 41 | PayloadOrganization 42 | SAP SE 43 | PayloadType 44 | com.apple.ManagedClient.preferences 45 | PayloadUUID 46 | 36132147-235E-4663-ADA8-2664C67C4DD2 47 | PayloadVersion 48 | 1 49 | 50 | 51 | PayloadDescription 52 | Configures the Privileges app. 53 | PayloadDisplayName 54 | Privileges configuration 55 | PayloadEnabled 56 | 57 | PayloadIdentifier 58 | CF401A42-35CA-4DA6-9123-5A49C87ECB5A 59 | PayloadOrganization 60 | SAP SE 61 | PayloadRemovalDisallowed 62 | 63 | PayloadScope 64 | System 65 | PayloadType 66 | Configuration 67 | PayloadUUID 68 | 50870D16-7AAD-478B-BFFE-BED09499F7E0 69 | PayloadVersion 70 | 1 71 | 72 | 73 | -------------------------------------------------------------------------------- /application_management/example_profiles/Example_LimitToUser.mobileconfig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PayloadContent 6 | 7 | 8 | PayloadContent 9 | 10 | corp.sap.privileges 11 | 12 | Forced 13 | 14 | 15 | mcx_preference_settings 16 | 17 | 25 | LimitToUser 26 | 27 | username_goes_here 28 | another_username_goes_here 29 | 30 | 31 | 32 | 33 | 34 | 35 | PayloadDescription 36 | 37 | PayloadDisplayName 38 | Privileges configuration 39 | PayloadEnabled 40 | 41 | PayloadIdentifier 42 | com.apple.ManagedClient.preferences.36132147-235E-4663-ADA8-2664C67C4DD2 43 | PayloadOrganization 44 | SAP SE 45 | PayloadType 46 | com.apple.ManagedClient.preferences 47 | PayloadUUID 48 | 36132147-235E-4663-ADA8-2664C67C4DD2 49 | PayloadVersion 50 | 1 51 | 52 | 53 | PayloadDescription 54 | Configures the Privileges app. 55 | PayloadDisplayName 56 | Privileges configuration 57 | PayloadEnabled 58 | 59 | PayloadIdentifier 60 | CF401A42-35CA-4DA6-9123-5A49C87ECB5A 61 | PayloadOrganization 62 | SAP SE 63 | PayloadRemovalDisallowed 64 | 65 | PayloadScope 66 | System 67 | PayloadType 68 | Configuration 69 | PayloadUUID 70 | 50870D16-7AAD-478B-BFFE-BED09499F7E0 71 | PayloadVersion 72 | 1 73 | 74 | 75 | -------------------------------------------------------------------------------- /application_management/example_profiles/Example_ReasonRequired.mobileconfig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PayloadContent 6 | 7 | 8 | PayloadContent 9 | 10 | corp.sap.privileges 11 | 12 | Forced 13 | 14 | 15 | mcx_preference_settings 16 | 17 | 26 | ReasonRequired 27 | 28 | 29 | 38 | ReasonMinLength 39 | 20 40 | 41 | 51 | ReasonMaxLength 52 | 50 53 | 54 | 63 | ReasonPresetList 64 | 65 | 66 | default 67 | Just for fun 68 | 69 | 70 | default 71 | For installing software 72 | 73 | 74 | default 75 | Don't know 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | PayloadDescription 84 | 85 | PayloadDisplayName 86 | Privileges configuration 87 | PayloadEnabled 88 | 89 | PayloadIdentifier 90 | com.apple.ManagedClient.preferences.36132147-235E-4663-ADA8-2664C67C4DD2 91 | PayloadOrganization 92 | SAP SE 93 | PayloadType 94 | com.apple.ManagedClient.preferences 95 | PayloadUUID 96 | 36132147-235E-4663-ADA8-2664C67C4DD2 97 | PayloadVersion 98 | 1 99 | 100 | 101 | PayloadDescription 102 | Configures the Privileges app. 103 | PayloadDisplayName 104 | Privileges configuration 105 | PayloadEnabled 106 | 107 | PayloadIdentifier 108 | CF401A42-35CA-4DA6-9123-5A49C87ECB5A 109 | PayloadOrganization 110 | SAP SE 111 | PayloadRemovalDisallowed 112 | 113 | PayloadScope 114 | System 115 | PayloadType 116 | Configuration 117 | PayloadUUID 118 | 50870D16-7AAD-478B-BFFE-BED09499F7E0 119 | PayloadVersion 120 | 1 121 | 122 | 123 | -------------------------------------------------------------------------------- /application_management/example_profiles/Example_RequireAuthentication.mobileconfig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PayloadContent 6 | 7 | 8 | PayloadContent 9 | 10 | corp.sap.privileges 11 | 12 | Forced 13 | 14 | 15 | mcx_preference_settings 16 | 17 | 27 | RequireAuthentication 28 | 29 | 30 | 38 | AllowCLIBiometricAuthentication 39 | 40 | 41 | 42 | 43 | 44 | 45 | PayloadDescription 46 | 47 | PayloadDisplayName 48 | Privileges configuration 49 | PayloadEnabled 50 | 51 | PayloadIdentifier 52 | com.apple.ManagedClient.preferences.36132147-235E-4663-ADA8-2664C67C4DD2 53 | PayloadOrganization 54 | SAP SE 55 | PayloadType 56 | com.apple.ManagedClient.preferences 57 | PayloadUUID 58 | 36132147-235E-4663-ADA8-2664C67C4DD2 59 | PayloadVersion 60 | 1 61 | 62 | 63 | PayloadDescription 64 | Configures the Privileges app. 65 | PayloadDisplayName 66 | Privileges configuration 67 | PayloadEnabled 68 | 69 | PayloadIdentifier 70 | CF401A42-35CA-4DA6-9123-5A49C87ECB5A 71 | PayloadOrganization 72 | SAP SE 73 | PayloadRemovalDisallowed 74 | 75 | PayloadScope 76 | System 77 | PayloadType 78 | Configuration 79 | PayloadUUID 80 | 50870D16-7AAD-478B-BFFE-BED09499F7E0 81 | PayloadVersion 82 | 1 83 | 84 | 85 | -------------------------------------------------------------------------------- /readme_images/CommandLine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/readme_images/CommandLine.png -------------------------------------------------------------------------------- /readme_images/DemoGIF.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/readme_images/DemoGIF.gif -------------------------------------------------------------------------------- /readme_images/DemoGIFviaDock.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/readme_images/DemoGIFviaDock.gif -------------------------------------------------------------------------------- /readme_images/DockIconCountDown 1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/readme_images/DockIconCountDown 1.png -------------------------------------------------------------------------------- /readme_images/IllustrationAppComponents.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/readme_images/IllustrationAppComponents.png -------------------------------------------------------------------------------- /readme_images/ManagedDockIcons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/readme_images/ManagedDockIcons.png -------------------------------------------------------------------------------- /readme_images/PrivilegesGranted.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/readme_images/PrivilegesGranted.jpg -------------------------------------------------------------------------------- /readme_images/PrivilegesRevoked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/readme_images/PrivilegesRevoked.png -------------------------------------------------------------------------------- /readme_images/PrivilegesToogleViaDock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/readme_images/PrivilegesToogleViaDock.png -------------------------------------------------------------------------------- /readme_images/RequestPrivilegesWindow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/readme_images/RequestPrivilegesWindow.png -------------------------------------------------------------------------------- /readme_images/RevertPrivilegesWindow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/readme_images/RevertPrivilegesWindow.png -------------------------------------------------------------------------------- /readme_images/RunAppWhenPrivilegeChange.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/readme_images/RunAppWhenPrivilegeChange.gif -------------------------------------------------------------------------------- /readme_images/UninstallationWindow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/readme_images/UninstallationWindow.png -------------------------------------------------------------------------------- /readme_images/console_show_privileges_process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/readme_images/console_show_privileges_process.png -------------------------------------------------------------------------------- /readme_images/console_show_privileges_process_filtered_for_admin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/readme_images/console_show_privileges_process_filtered_for_admin.png -------------------------------------------------------------------------------- /readme_images/github banner new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/readme_images/github banner new.png -------------------------------------------------------------------------------- /readme_images/locked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/readme_images/locked.png -------------------------------------------------------------------------------- /readme_images/locked_managed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/readme_images/locked_managed.png -------------------------------------------------------------------------------- /readme_images/log_show_privileges_process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/readme_images/log_show_privileges_process.png -------------------------------------------------------------------------------- /readme_images/log_show_privileges_process_filtered_for_admin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/readme_images/log_show_privileges_process_filtered_for_admin.png -------------------------------------------------------------------------------- /readme_images/renewal_custom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/readme_images/renewal_custom.png -------------------------------------------------------------------------------- /readme_images/settings_general.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/readme_images/settings_general.png -------------------------------------------------------------------------------- /readme_images/settings_managed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/readme_images/settings_managed.png -------------------------------------------------------------------------------- /readme_images/settings_privileges.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/readme_images/settings_privileges.png -------------------------------------------------------------------------------- /readme_images/unlocked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/readme_images/unlocked.png -------------------------------------------------------------------------------- /readme_images/unlocked_managed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/readme_images/unlocked_managed.png -------------------------------------------------------------------------------- /source/Privileges.xcodeproj/project.xcworkspace/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/source/Privileges.xcodeproj/project.xcworkspace/.DS_Store -------------------------------------------------------------------------------- /source/Privileges.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /source/Privileges.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /source/Privileges.xcodeproj/xcshareddata/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/source/Privileges.xcodeproj/xcshareddata/.DS_Store -------------------------------------------------------------------------------- /source/Privileges.xcodeproj/xcshareddata/xcschemes/Privileges Beta.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 9 | 10 | 16 | 22 | 23 | 24 | 25 | 26 | 32 | 33 | 43 | 45 | 51 | 52 | 53 | 54 | 60 | 62 | 68 | 69 | 70 | 71 | 73 | 74 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /source/Privileges.xcodeproj/xcshareddata/xcschemes/Privileges.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 9 | 10 | 16 | 22 | 23 | 24 | 25 | 26 | 31 | 32 | 35 | 36 | 37 | 38 | 48 | 50 | 56 | 57 | 58 | 59 | 65 | 67 | 73 | 74 | 75 | 76 | 78 | 79 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /source/Privileges/AppDelegate.h: -------------------------------------------------------------------------------- 1 | /* 2 | AppDelegate.h 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | @interface AppDelegate : NSObject 21 | 22 | @end 23 | 24 | -------------------------------------------------------------------------------- /source/Privileges/AppleScript sample.scpt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/source/Privileges/AppleScript sample.scpt -------------------------------------------------------------------------------- /source/Privileges/Beta-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSDockTilePlugIn 6 | PrivilegesTile.docktileplugin 7 | 8 | 9 | -------------------------------------------------------------------------------- /source/Privileges/Credits.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\ansicpg1252\cocoartf2761 2 | \cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fnil\fcharset0 SFPro-Regular;} 3 | {\colortbl;\red255\green255\blue255;\red0\green0\blue0;\red0\green0\blue0;} 4 | {\*\expandedcolortbl;;\cssrgb\c0\c0\c0\c49804\cname secondaryLabelColor;\csgray\c0\c0;} 5 | \paperw11900\paperh16840\vieww20740\viewh8340\viewkind0 6 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc\partightenfactor0 7 | 8 | \f0\fs20 \cf2 \cb3 \ 9 | Design & Engineering\ 10 | Marc Thielemann\ 11 | \ 12 | \pard\pardeftab720\qc\partightenfactor0 13 | \cf2 \expnd0\expndtw0\kerning0 14 | This application can be redistributed\ 15 | and modified under \kerning1\expnd0\expndtw0 the\ 16 | \pard\pardeftab720\qc\partightenfactor0 17 | {\field{\*\fldinst{HYPERLINK "http://www.apache.org/licenses/LICENSE-2.0"}}{\fldrslt \cf2 Apache License, Version 2.0}}\expnd0\expndtw0\kerning0 18 | \ 19 | } -------------------------------------------------------------------------------- /source/Privileges/MTReasonAccessory.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /source/Privileges/Privileges-ParentConstraint.coderequirement: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | is-init-proc 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /source/Privileges/Privileges-SelfConstraint.coderequirement: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | launch-type 6 | 3 7 | 8 | 9 | -------------------------------------------------------------------------------- /source/Privileges/Privileges.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.application-groups 8 | 9 | $(TeamIdentifierPrefix)corp.sap.privileges 10 | 11 | com.apple.security.files.user-selected.read-only 12 | 13 | com.apple.security.temporary-exception.shared-preference.read-write 14 | corp.sap.privileges.docktileplugin 15 | 16 | 17 | -------------------------------------------------------------------------------- /source/Privileges/Release-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSDockTilePlugIn 6 | PrivilegesTile.docktileplugin 7 | 8 | 9 | -------------------------------------------------------------------------------- /source/Privileges/View Controllers/MTReasonAccessoryController.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTReasonAccessoryController.h 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | @interface MTReasonAccessoryController : NSViewController 21 | @property (weak) IBOutlet NSPopUpButton *predefinedReasonsButton; 22 | @property (weak) IBOutlet NSTextField *reasonTextField; 23 | @end 24 | -------------------------------------------------------------------------------- /source/Privileges/View Controllers/MTReasonAccessoryController.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTReasonAccessoryController.m 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTReasonAccessoryController.h" 19 | #import "MTPrivileges.h" 20 | #import "Constants.h" 21 | 22 | @interface MTReasonAccessoryController () 23 | @property (nonatomic, strong, readwrite) NSString *reasonPlaceHolder; 24 | @end 25 | 26 | @implementation MTReasonAccessoryController 27 | 28 | - (void)viewDidLoad 29 | { 30 | [super viewDidLoad]; 31 | 32 | MTPrivileges *privilegesApp = [[MTPrivileges alloc] init]; 33 | 34 | [_predefinedReasonsButton setHidden:YES]; 35 | [[_predefinedReasonsButton menu] removeAllItems]; 36 | 37 | NSInteger minLength = [privilegesApp reasonMinLength]; 38 | _reasonPlaceHolder = [NSString localizedStringWithFormat:NSLocalizedString(@"minLengthPlaceholder", nil), minLength]; 39 | 40 | [_reasonTextField setPlaceholderString:_reasonPlaceHolder]; 41 | 42 | // create the menu with pre-defined reasons (if configured) 43 | if ([privilegesApp reasonRequired]) { 44 | 45 | NSArray *predefinedReasons = [privilegesApp predefinedReasons]; 46 | 47 | if (predefinedReasons && [predefinedReasons count] > 0) { 48 | 49 | NSMutableArray *allReasons = [[NSMutableArray alloc] init]; 50 | NSString *languageCode = [[NSLocale currentLocale] languageCode]; 51 | 52 | for (NSDictionary *aReason in predefinedReasons) { 53 | 54 | if ([aReason isKindOfClass:[NSDictionary class]]) { 55 | NSString *localizedReasonString = [aReason objectForKey:languageCode]; 56 | if (!localizedReasonString) { localizedReasonString = [aReason objectForKey:@"default"]; } 57 | if (!localizedReasonString) { localizedReasonString = [aReason objectForKey:@"en"]; } 58 | if (localizedReasonString) { [allReasons addObject:localizedReasonString]; } 59 | } 60 | } 61 | 62 | if ([allReasons count] > 0) { 63 | 64 | [allReasons insertObject:NSLocalizedString(@"otherMenuEntry", nil) atIndex:0]; 65 | 66 | for (NSString *aReason in allReasons) { 67 | 68 | [[_predefinedReasonsButton menu] addItemWithTitle:aReason 69 | action:nil 70 | keyEquivalent:@"" 71 | ]; 72 | } 73 | 74 | [_predefinedReasonsButton setHidden:NO]; 75 | } 76 | } 77 | } 78 | } 79 | 80 | - (IBAction)selectPredefinedReason:(id)sender 81 | { 82 | if ([_predefinedReasonsButton indexOfSelectedItem] == 0) { 83 | 84 | [_reasonTextField setEnabled:YES]; 85 | [_reasonTextField setTextColor:[NSColor textColor]]; 86 | [_reasonTextField setPlaceholderString:_reasonPlaceHolder]; 87 | [_reasonTextField selectText:nil]; 88 | 89 | } else { 90 | 91 | [_reasonTextField setEnabled:NO]; 92 | [_reasonTextField setTextColor:[NSColor clearColor]]; 93 | [_reasonTextField setPlaceholderString:nil]; 94 | } 95 | } 96 | 97 | @end 98 | -------------------------------------------------------------------------------- /source/Privileges/View Controllers/MTSettingsGeneralController.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTSettingsGeneralController.h 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | @interface MTSettingsGeneralController : NSViewController 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /source/Privileges/View Controllers/MTSettingsGeneralController.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTSettingsGeneralController.m 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTSettingsGeneralController.h" 19 | #import "MTPrivileges.h" 20 | #import "Constants.h" 21 | 22 | @interface MTSettingsGeneralController () 23 | @property (retain) id configurationObserver; 24 | @property (nonatomic, strong, readwrite) MTPrivileges *privilegesApp; 25 | @property (nonatomic, strong, readwrite) NSString *configuredByProfileLabel; 26 | 27 | @property (weak) IBOutlet NSButton *hideWindowsButton; 28 | @property (weak) IBOutlet NSButton *menuBarButton; 29 | @end 30 | 31 | @implementation MTSettingsGeneralController 32 | 33 | - (void)viewDidLoad 34 | { 35 | [super viewDidLoad]; 36 | 37 | [[[self view] window] setAccessibilityLabel:[[[self view] window] title]]; 38 | [[[self view] window] setAccessibilityEnabled:YES]; 39 | 40 | _privilegesApp = [[MTPrivileges alloc] init]; 41 | 42 | // set the initial state of the "Hide other windows" checkbox 43 | [self setHideWindowsCheckbox]; 44 | 45 | // set the initial state of the "Show in Menu Bar" checkbox 46 | [self setMenuBarCheckbox]; 47 | 48 | self.configuredByProfileLabel = NSLocalizedString(@"configuredByProfileLabel", nil); 49 | 50 | _configurationObserver = [[NSDistributedNotificationCenter defaultCenter] addObserverForName:kMTNotificationNameConfigDidChange 51 | object:nil 52 | queue:nil 53 | usingBlock:^(NSNotification *notification) { 54 | NSDictionary *userInfo = [notification userInfo]; 55 | 56 | if (userInfo) { 57 | 58 | NSString *changedKey = [userInfo objectForKey:kMTNotificationKeyPreferencesChanged]; 59 | 60 | NSArray *keysToObserve = [[NSArray alloc] initWithObjects: 61 | kMTDefaultsHideOtherWindowsKey, 62 | kMTDefaultsShowInMenuBarKey, 63 | nil 64 | ]; 65 | 66 | if (changedKey && [keysToObserve containsObject:changedKey]) { 67 | 68 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 69 | 70 | if ([changedKey isEqualToString:kMTDefaultsHideOtherWindowsKey]) { 71 | 72 | [self setHideWindowsCheckbox]; 73 | 74 | } else if ([changedKey isEqualToString:kMTDefaultsShowInMenuBarKey]) { 75 | 76 | [self setMenuBarCheckbox]; 77 | } 78 | }); 79 | } 80 | } 81 | }]; 82 | } 83 | 84 | - (void)setHideWindowsCheckbox 85 | { 86 | [self willChangeValueForKey:@"hideWindowsIsForced"]; 87 | [_hideWindowsButton setState:([_privilegesApp hideOtherWindows]) ? NSControlStateValueOn : NSControlStateValueOff]; 88 | [_hideWindowsButton setEnabled:![_privilegesApp hideOtherWindowsIsForced]]; 89 | [self didChangeValueForKey:@"hideWindowsIsForced"]; 90 | } 91 | 92 | - (void)setMenuBarCheckbox 93 | { 94 | [self willChangeValueForKey:@"menuBarIsForced"]; 95 | [_menuBarButton setState:([_privilegesApp showInMenuBar]) ? NSControlStateValueOn : NSControlStateValueOff]; 96 | [_menuBarButton setEnabled:![_privilegesApp showInMenuBarIsForced]]; 97 | [self didChangeValueForKey:@"menuBarIsForced"]; 98 | } 99 | 100 | - (void)dealloc 101 | { 102 | [[NSDistributedNotificationCenter defaultCenter] removeObserver:_configurationObserver]; 103 | _configurationObserver = nil; 104 | } 105 | 106 | #pragma mark Bindings 107 | 108 | - (BOOL)hideWindowsIsForced 109 | { 110 | return [_privilegesApp hideOtherWindowsIsForced]; 111 | } 112 | 113 | - (BOOL)menuBarIsForced 114 | { 115 | return [_privilegesApp showInMenuBarIsForced]; 116 | } 117 | 118 | 119 | #pragma mark IBActions 120 | 121 | - (IBAction)setHideOtherWindows:(id)sender 122 | { 123 | [_privilegesApp setHideOtherWindows:([(NSButton*)sender state] == NSControlStateValueOn)]; 124 | } 125 | 126 | - (IBAction)setShowInMenuBar:(id)sender 127 | { 128 | [_privilegesApp setShowInMenuBar:([(NSButton*)sender state] == NSControlStateValueOn)]; 129 | } 130 | 131 | @end 132 | -------------------------------------------------------------------------------- /source/Privileges/View Controllers/MTSettingsPrivilegesController.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTSettingsPrivilegesController.h 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | @interface MTSettingsPrivilegesController : NSViewController 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /source/Privileges/View Controllers/MTTabViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTTabViewController.h 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | @interface MTTabViewController : NSTabViewController 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /source/Privileges/View Controllers/MTTabViewController.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTTabViewController.m 3 | Copyright 2023-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTTabViewController.h" 19 | #import "Constants.h" 20 | 21 | @interface MTTabViewController () 22 | @property (assign) BOOL allowSelection; 23 | @end 24 | 25 | @implementation MTTabViewController 26 | 27 | - (void)viewDidLoad 28 | { 29 | [super viewDidLoad]; 30 | 31 | // select the last tab the user selected 32 | NSInteger selectedTabIndex = [[NSUserDefaults standardUserDefaults] integerForKey:kMTDefaultsSettingsSelectedTabKey]; 33 | _allowSelection = YES; 34 | 35 | if (selectedTabIndex >= 0 && selectedTabIndex < [[self tabViewItems] count]) { 36 | [self setSelectedTabViewItemIndex:selectedTabIndex]; 37 | } else { 38 | [self setSelectedTabViewItemIndex:0]; 39 | } 40 | } 41 | 42 | - (void)viewWillAppear 43 | { 44 | [super viewWillAppear]; 45 | [self updateWindowTitle]; 46 | } 47 | 48 | - (void)tabView:(NSTabView *)tabView didSelectTabViewItem:(NSTabViewItem *)tabViewItem 49 | { 50 | [super tabView:tabView didSelectTabViewItem:tabViewItem]; 51 | [self updateWindowTitle]; 52 | 53 | // we ignore the initial tab selection (the one we had to define in Xcode) 54 | if (_allowSelection) { 55 | 56 | [[NSUserDefaults standardUserDefaults] setInteger:[tabView indexOfTabViewItem:[tabView selectedTabViewItem]] 57 | forKey:kMTDefaultsSettingsSelectedTabKey 58 | ]; 59 | } 60 | } 61 | 62 | - (void)updateWindowTitle 63 | { 64 | // set the window title to the label of the selected tab 65 | NSTabViewItem *selectedItem = [[self tabView] selectedTabViewItem]; 66 | [[[self tabView] window] setTitle:[selectedItem label]]; 67 | } 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /source/Privileges/corp.sap.privileges.agent.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | MachServices 6 | 7 | corp.sap.privileges.agent.xpc 8 | 9 | 10 | Label 11 | corp.sap.privileges.agent 12 | Program 13 | /Applications/Privileges.app/Contents/MacOS/PrivilegesAgent.app/Contents/MacOS/PrivilegesAgent 14 | AssociatedBundleIdentifiers 15 | corp.sap.privileges 16 | SpawnConstraint 17 | 18 | team-identifier 19 | 7R5ZEU67FQ 20 | signing-identifier 21 | corp.sap.privileges.agent 22 | 23 | RunAtLoad 24 | 25 | KeepAlive 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /source/Privileges/corp.sap.privileges.daemon.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | MachServices 6 | 7 | corp.sap.privileges.daemon.xpc 8 | 9 | 10 | Label 11 | corp.sap.privileges.daemon 12 | Program 13 | /Applications/Privileges.app/Contents/MacOS/PrivilegesDaemon 14 | AssociatedBundleIdentifiers 15 | corp.sap.privileges 16 | SpawnConstraint 17 | 18 | team-identifier 19 | 7R5ZEU67FQ 20 | signing-identifier 21 | corp.sap.privileges.daemon 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /source/Privileges/corp.sap.privileges.watcher.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Label 6 | corp.sap.privileges.watcher 7 | Program 8 | /Applications/Privileges.app/Contents/MacOS/PrivilegesWatcher 9 | WatchPaths 10 | 11 | /var/db/dslocal/nodes/Default/groups/admin.plist 12 | 13 | AssociatedBundleIdentifiers 14 | corp.sap.privileges 15 | SpawnConstraint 16 | 17 | team-identifier 18 | 7R5ZEU67FQ 19 | signing-identifier 20 | corp.sap.privileges.watcher 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /source/Privileges/main.m: -------------------------------------------------------------------------------- 1 | /* 2 | main.m 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | int main(int argc, const char * argv[]) 21 | { 22 | return NSApplicationMain(argc, argv); 23 | } 24 | -------------------------------------------------------------------------------- /source/PrivilegesAgent/AppDelegate.h: -------------------------------------------------------------------------------- 1 | /* 2 | AppDelegate.h 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | #import "MTLocalNotification.h" 20 | 21 | /*! 22 | @protocol AppleScriptDataProvider 23 | @abstract Defines an interface for accessing some of the PrivilegesAgent's values via AppleScript. 24 | */ 25 | @protocol AppleScriptDataProvider 26 | 27 | /*! 28 | @method privilegesTimeLeft 29 | @abstract Get the number of minutes remaining until the current user's administrator privileges expire. 30 | @discussion Returns the number of minutes remaining until the current user's administrator privileges expire, 31 | or 0 if the user does not have administrator privileges. 32 | */ 33 | - (NSUInteger)privilegesTimeLeft; 34 | 35 | /*! 36 | @method userHasAdminPrivileges: 37 | @abstract Get whether the current user has administrator privileges. 38 | @discussion Returns YES if the current user has administrator privileges, otherwise returns NO. 39 | */ 40 | - (BOOL)userHasAdminPrivileges; 41 | 42 | @end 43 | 44 | @interface AppDelegate : NSObject 45 | 46 | @end 47 | 48 | -------------------------------------------------------------------------------- /source/PrivilegesAgent/Classes/MTClientCertificate.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTClientCertificate.h 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | /*! 21 | @class MTClientCertificate 22 | @abstract A class that provides methods to find a matching identity for a given distinguished name. 23 | */ 24 | 25 | @interface MTClientCertificate : NSObject 26 | 27 | /*! 28 | @method init 29 | @discussion The init method is not available. Please use initWithinitWithDistinguishedName: instead. 30 | */ 31 | - (instancetype)init NS_UNAVAILABLE; 32 | 33 | /*! 34 | @method initWithinitWithDistinguishedName: 35 | @abstract Initialize a MTClientCertificate object with a given NSData object containing a DER 36 | encoded distinguished name. 37 | @param encodedData The DER-encoded distinguished name. 38 | @discussion Returns an initialized MTClientCertificate object or nil if an error occurred. 39 | */ 40 | - (instancetype)initWithDistinguishedName:(NSData*)encodedData NS_DESIGNATED_INITIALIZER; 41 | 42 | /*! 43 | @method dictionaryRepresentation 44 | @abstract Get a dictionary representation of the DN containing all its OIDs and their respective values. 45 | @discussion Returns a NSDictionary with OIDs and its values or nil if an error occurred. 46 | */ 47 | - (NSDictionary*)dictionaryRepresentation; 48 | 49 | /*! 50 | @method matchingIdentityWithSecItems: 51 | @abstract Initialize a MTClientCertificate object with a given NSData object containing a DER 52 | encoded distinguished name. 53 | @param secItems An array of SecIdentityRef. 54 | @discussion Returns the first SecIdentityRef that matches the DN the MTClientCertificate object 55 | has been initialized with or nil if an error occurred. 56 | */ 57 | - (SecIdentityRef)matchingIdentityWithSecItems:(NSArray*)secItems; 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /source/PrivilegesAgent/Classes/MTDaemonConnection.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTDaemonConnection.h 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | #import "PrivilegesDaemonProtocol.h" 20 | #import 21 | #import 22 | 23 | /*! 24 | @class MTDaemonConnection 25 | @abstract A class that provides an easy way to connect to the Privileges daemon. 26 | */ 27 | 28 | @interface MTDaemonConnection : NSObject 29 | 30 | /*! 31 | @property connection 32 | @abstract A property to store the connection object. 33 | @discussion The value of this property is NSXPCConnection. 34 | */ 35 | @property (atomic, strong, readonly) NSXPCConnection *connection; 36 | 37 | /*! 38 | @method connectToDaemonWithExportedObject:andExecuteCommandBlock: 39 | @abstract Connects to the daemon and executes the given command block. 40 | @param commandBlock The command block that should be executed after the connection has been established. 41 | */ 42 | - (void)connectToDaemonAndExecuteCommandBlock:(void(^)(void))commandBlock; 43 | 44 | /*! 45 | @method invalidate 46 | @abstract Invalidates the connection to the daemon (and xpc service). 47 | */ 48 | - (void)invalidate; 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /source/PrivilegesAgent/Classes/MTDaemonConnection.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTDaemonConnection.m 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTDaemonConnection.h" 19 | #import "Constants.h" 20 | 21 | @interface MTDaemonConnection () 22 | @property (atomic, strong, readwrite) NSXPCConnection *connection; 23 | @property (atomic, strong, readwrite) NSXPCListenerEndpoint *listenerEndpoint; 24 | @property (nonatomic, strong, readwrite) NSTimer *xpcTimeoutTimer; 25 | @end 26 | 27 | 28 | @implementation MTDaemonConnection 29 | 30 | - (void)connectToDaemonAndExecuteCommandBlock:(void(^)(void))commandBlock 31 | { 32 | if (!_connection) { 33 | 34 | _connection = [[NSXPCConnection alloc] initWithMachServiceName:kMTDaemonMachServiceName 35 | options:NSXPCConnectionPrivileged 36 | ]; 37 | [_connection setRemoteObjectInterface:[NSXPCInterface interfaceWithProtocol:@protocol(PrivilegesDaemonProtocol)]]; 38 | 39 | #pragma clang diagnostic push 40 | #pragma clang diagnostic ignored "-Warc-retain-cycles" 41 | [_connection setInvalidationHandler:^{ 42 | 43 | [self->_connection setInvalidationHandler:nil]; 44 | dispatch_async(dispatch_get_main_queue(), ^{ 45 | os_log(OS_LOG_DEFAULT, "SAPCorp: Daemon connection invalidated"); 46 | self->_connection = nil; 47 | }); 48 | }]; 49 | 50 | [_connection setInterruptionHandler:^{ 51 | 52 | [self->_connection setInterruptionHandler:nil]; 53 | dispatch_async(dispatch_get_main_queue(), ^{ 54 | os_log(OS_LOG_DEFAULT, "SAPCorp: Daemon connection interrupted"); 55 | self->_connection = nil; 56 | }); 57 | }]; 58 | #pragma clang diagnostic pop 59 | 60 | [_connection resume]; 61 | } 62 | 63 | // and execute the command block 64 | commandBlock(); 65 | 66 | dispatch_async(dispatch_get_main_queue(), ^{ 67 | 68 | self->_xpcTimeoutTimer = [NSTimer scheduledTimerWithTimeInterval:60 69 | repeats:NO 70 | block:^(NSTimer *timer) { 71 | [self invalidate]; 72 | }]; 73 | }); 74 | } 75 | 76 | - (void)invalidate 77 | { 78 | if (_connection) { [_connection invalidate]; } 79 | } 80 | 81 | @end 82 | -------------------------------------------------------------------------------- /source/PrivilegesAgent/Classes/MTLocalNotification.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTLocalNotification.h 3 | Copyright 2022-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | #import 20 | 21 | @interface MTLocalNotification : NSObject 22 | 23 | /*! 24 | @enum MTLocalNotificationType 25 | @abstract Specifies the type of a notification. 26 | @constant MTLocalNotificationTypeNoChange Specifies a notification that informs the user that privileges have not been changed. 27 | @constant MTLocalNotificationTypeGrantSuccess Specifies a notification that informs the user that administrator privileges have been granted. 28 | @constant MTLocalNotificationTypeRevokeSuccess Specifies a notification that informs the user that administrator privileges have been revoked. 29 | @constant MTLocalNotificationTypeError Specifies a notification that informs the user that privileges could not be changed due to an error. 30 | @constant MTLocalNotificationTypeRenew Specifies a notification that informs the user that administrator privileges are about to expire and asks to renew privileges. 31 | @constant MTLocalNotificationTypeRenewSuccess Specifies a notification that informs the user that administrator privileges have been renewed. 32 | */ 33 | typedef enum { 34 | MTLocalNotificationTypeNoChange = 0, 35 | MTLocalNotificationTypeGrantSuccess = 1, 36 | MTLocalNotificationTypeRevokeSuccess = 2, 37 | MTLocalNotificationTypeError = 3, 38 | MTLocalNotificationTypeRenew = 4, 39 | MTLocalNotificationTypeRenewSuccess = 5, 40 | } MTLocalNotificationType; 41 | 42 | @property (nonatomic, strong, readwrite) NSArray *actions; 43 | @property (nonatomic, strong, readwrite) NSString *categoryIdentifier; 44 | @property (weak) id delegate; 45 | 46 | /*! 47 | @method requestAuthorizationWithCompletionHandler: 48 | @abstract Requests a user's authorization to allow local and remote notifications for the app. 49 | @param completionHandler The handler to call when the request is complete. 50 | @discussion Returns YES if the user granted authorization, otherwise returns NO. In case of an error the error object might contain 51 | information about the error that caused the operation to fail. 52 | */ 53 | - (void)requestAuthorizationWithCompletionHandler:(void (^)(BOOL granted, NSError *error))completionHandler; 54 | 55 | /*! 56 | @method sendNotificationWithTitle:message:userInfo:replaceExisting: 57 | @abstract Sends a notification to the user notificatiion center. 58 | @param title The title of the notification. 59 | @param message The notification body (the message). 60 | @param userInfo An optional dictionary containing custom data to associate with the notification. 61 | @param replaceExisting A boolean specifying if existing notification should be removed or not. 62 | @param action A boolean specifying if the notification should have an action attached. 63 | @param completionHandler The handler to call when the request is complete. 64 | @discussion The returned error object might contain error information if an error occurred or will be nil if no error occurred. 65 | */ 66 | - (void)sendNotificationWithTitle:(NSString*)title 67 | message:(NSString*)message 68 | userInfo:(NSDictionary*)userInfo 69 | replaceExisting:(BOOL)replaceExisting 70 | action:(BOOL)action 71 | completionHandler:(void (^)(NSError *error))completionHandler; 72 | 73 | @end 74 | -------------------------------------------------------------------------------- /source/PrivilegesAgent/Classes/MTLocalNotification.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTLocalNotification.m 3 | Copyright 2022-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTLocalNotification.h" 19 | #import "Constants.h" 20 | 21 | @implementation MTLocalNotification 22 | 23 | - (void)requestAuthorizationWithCompletionHandler:(void (^)(BOOL granted, NSError *error))completionHandler 24 | { 25 | UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; 26 | [center requestAuthorizationWithOptions:( 27 | UNAuthorizationOptionAlert | 28 | UNAuthorizationOptionSound | 29 | UNAuthorizationOptionBadge 30 | ) 31 | completionHandler:^(BOOL granted, NSError *error) { 32 | if (completionHandler) { completionHandler(granted, error); } 33 | }]; 34 | } 35 | 36 | - (void)sendNotificationWithTitle:(NSString*)title 37 | message:(NSString*)message 38 | userInfo:(NSDictionary*)userInfo 39 | replaceExisting:(BOOL)replaceExisting 40 | action:(BOOL)action 41 | completionHandler:(void (^)(NSError *error))completionHandler; 42 | { 43 | 44 | 45 | UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; 46 | [center setDelegate:_delegate]; 47 | 48 | UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init]; 49 | [content setTitle:title]; 50 | [content setBody:message]; 51 | [content setSound:[UNNotificationSound defaultSound]]; 52 | [content setUserInfo:userInfo]; 53 | 54 | if (action && [_actions count] > 0 && _categoryIdentifier) { 55 | 56 | UNNotificationCategory *category = [UNNotificationCategory categoryWithIdentifier:_categoryIdentifier 57 | actions:_actions 58 | intentIdentifiers:[NSArray new] 59 | options:UNNotificationCategoryOptionCustomDismissAction 60 | ]; 61 | 62 | [content setCategoryIdentifier:_categoryIdentifier]; 63 | [center setNotificationCategories:[NSSet setWithObject:category]]; 64 | } 65 | 66 | UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:[[NSUUID UUID] UUIDString] 67 | content:content 68 | trigger:nil 69 | ]; 70 | 71 | // remove existing notifications 72 | if (replaceExisting) { 73 | [center removeAllDeliveredNotifications]; 74 | [NSThread sleepForTimeInterval:.5]; 75 | } 76 | 77 | [center addNotificationRequest:request 78 | withCompletionHandler:^(NSError *error) { 79 | 80 | if (completionHandler) { completionHandler(error); } 81 | }]; 82 | } 83 | 84 | @end 85 | -------------------------------------------------------------------------------- /source/PrivilegesAgent/Classes/MTPrivilegeExpirationCommand.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTPrivilegeExpirationCommand.h 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | /*! 21 | @class MTPrivilegeExpirationCommand 22 | @abstract This class contains the code for the AppleScript command "expiration of administrator privileges". 23 | */ 24 | 25 | @interface MTPrivilegeExpirationCommand : NSScriptCommand 26 | 27 | @end 28 | 29 | -------------------------------------------------------------------------------- /source/PrivilegesAgent/Classes/MTPrivilegeExpirationCommand.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTPrivilegeExpirationCommand.m 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTPrivilegeExpirationCommand.h" 19 | #import "AppDelegate.h" 20 | 21 | @implementation MTPrivilegeExpirationCommand 22 | 23 | - (id)performDefaultImplementation 24 | { 25 | NSUInteger timeLeft = 0; 26 | AppDelegate *appDelegate = (AppDelegate*)[NSApp delegate]; 27 | 28 | if ([appDelegate conformsToProtocol:@protocol(AppleScriptDataProvider)]) { 29 | 30 | if ([appDelegate respondsToSelector:@selector(privilegesTimeLeft)]) { 31 | timeLeft = [appDelegate privilegesTimeLeft]; 32 | } 33 | } 34 | 35 | return [NSNumber numberWithUnsignedInteger:timeLeft]; 36 | } 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /source/PrivilegesAgent/Classes/MTPrivilegeStatusCommand.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTPrivilegeStatusCommand.h 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | /*! 21 | @class MTPrivilegeStatusCommand 22 | @abstract This class contains the code for the AppleScript command "status of administrator privileges". 23 | */ 24 | 25 | @interface MTPrivilegeStatusCommand : NSScriptCommand 26 | 27 | @end 28 | 29 | -------------------------------------------------------------------------------- /source/PrivilegesAgent/Classes/MTPrivilegeStatusCommand.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTPrivilegeStatusCommand.m 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTPrivilegeStatusCommand.h" 19 | #import "AppDelegate.h" 20 | 21 | @implementation MTPrivilegeStatusCommand 22 | 23 | - (id)performDefaultImplementation 24 | { 25 | BOOL hasAdminPrivileges = NO; 26 | AppDelegate *appDelegate = (AppDelegate*)[NSApp delegate]; 27 | 28 | if ([appDelegate conformsToProtocol:@protocol(AppleScriptDataProvider)]) { 29 | 30 | if ([appDelegate respondsToSelector:@selector(userHasAdminPrivileges)]) { 31 | hasAdminPrivileges = [appDelegate userHasAdminPrivileges]; 32 | } 33 | } 34 | 35 | return [NSNumber numberWithBool:hasAdminPrivileges]; 36 | } 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /source/PrivilegesAgent/Classes/MTStatusItemMenu.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTStatusItemMenu.h 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | /*! 21 | @class MTStatusItemMenu 22 | @abstract This class defines the menu for the status item. 23 | */ 24 | 25 | @interface MTStatusItemMenu : NSMenu 26 | 27 | /*! 28 | @method updateMenu 29 | @abstract Updates the menu and makes sure the menu items are named and enabled/disabled 30 | according to the user's current privileges and configuration. 31 | */ 32 | - (void)updateMenu; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /source/PrivilegesAgent/Classes/MTStatusItemMenu.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTStatusItemMenu.m 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTStatusItemMenu.h" 19 | #import "MTPrivileges.h" 20 | #import "Constants.h" 21 | 22 | @implementation MTStatusItemMenu 23 | 24 | - (instancetype)init 25 | { 26 | self = [super init]; 27 | 28 | if (self) { [self setUpView]; } 29 | 30 | return self; 31 | } 32 | 33 | - (instancetype)initWithCoder:(NSCoder *)coder 34 | { 35 | self = [super initWithCoder:coder]; 36 | 37 | if (self) { [self setUpView]; } 38 | 39 | return self; 40 | } 41 | 42 | - (void)setUpView 43 | { 44 | [self setDelegate:self]; 45 | [self setAutoenablesItems:NO]; 46 | } 47 | 48 | - (void)updateMenu 49 | { 50 | MTPrivileges *privilegesApp = [[MTPrivileges alloc] init]; 51 | BOOL hasAdminPrivileges = [[privilegesApp currentUser] hasAdminPrivileges]; 52 | 53 | if (hasAdminPrivileges) { 54 | 55 | [[self itemWithTag:1000] setTitle:NSLocalizedStringFromTable(@"revertMenuItem", @"LocalizableMenu", nil)]; 56 | 57 | } else { 58 | 59 | [[self itemWithTag:1000] setTitle:NSLocalizedStringFromTable(@"requestMenuItem", @"LocalizableMenu", nil)]; 60 | } 61 | 62 | [[self itemWithTag:1000] setEnabled:!([[privilegesApp currentUser] useIsRestricted] || (!hasAdminPrivileges && [privilegesApp reasonRequired]))]; 63 | [[self itemWithTag:2000] setAlternate:(hasAdminPrivileges && [privilegesApp privilegeRenewalAllowed] && [privilegesApp expirationInterval] > 0 && ![[privilegesApp currentUser] hasUnexpectedPrivilegeState])]; 64 | [[self itemWithTag:2000] setHidden:![[self itemWithTag:2000] isAlternate]]; 65 | } 66 | 67 | - (void)menuWillOpen:(NSMenu *)menu 68 | { 69 | [self updateMenu]; 70 | } 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /source/PrivilegesAgent/Classes/MTSyslogMessageStructuredData.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTSyslogMessageStructuredData.h 3 | Copyright 2020-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | /*! 21 | @class MTSyslogMessageStructuredData 22 | @abstract This class provides methods for creating the structured data part of a syslog message (as defined in RFC 5424). 23 | */ 24 | 25 | @interface MTSyslogMessageStructuredData : NSObject 26 | 27 | /*! 28 | @method addStructuredData:withID: 29 | @abstract Add an element to the structured data object. 30 | @param data A dictionary containing the keys and values of the element. 31 | @param sdID The id/name of the element. 32 | */ 33 | - (void)addStructuredData:(NSDictionary*)data withID:(NSString*)sdID; 34 | 35 | /*! 36 | @method structuredDataWithDictionary: 37 | @abstract Create the structured data object from a given dictionary. 38 | @param data A dictionary containing one or more structured data element(s). 39 | @discussion The following example shows a dictionary with two structured data elements: 40 | @code 41 | { 42 | exampleSDID@32473 = { 43 | iut = 3; 44 | eventSource = Application; 45 | eventID = 1011; 46 | }; 47 | examplePriority@32473 = { 48 | class = high; 49 | } 50 | } 51 | */ 52 | - (void)structuredDataWithDictionary:(NSDictionary*)data; 53 | 54 | /*! 55 | @method composedString 56 | @abstract Get the stuctured data as RFC 5424-compliant structured data string. 57 | @discussion Returns a string containing the structured data or nil if no data has been added or an error occurred. 58 | */ 59 | - (NSString*)composedString; 60 | 61 | /*! 62 | @method cleanString:maximumLength: 63 | @abstract Converts the given string into US-ASCII and removes non-printable characters, ensuring the given maximum length. 64 | @param originalString The string that should be converted. 65 | @param maxLength The maximum length that the converted string should not exceed. If set to 0, the length is unlimited. 66 | @discussion Returns the cleaned string or nil if an error occurred. 67 | */ 68 | + (NSString*)cleanString:(NSString*)originalString maximumLength:(NSInteger)maxLength; 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /source/PrivilegesAgent/Classes/MTSyslogMessageStructuredData.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTSyslogMessageStructuredData.m 3 | Copyright 2020-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTSyslogMessageStructuredData.h" 19 | 20 | @interface MTSyslogMessageStructuredData () 21 | @property (nonatomic, strong, readwrite) NSMutableDictionary *structuredData; 22 | @end 23 | 24 | @implementation MTSyslogMessageStructuredData 25 | 26 | - (instancetype)init 27 | { 28 | self = [super init]; 29 | 30 | if (self) { 31 | 32 | _structuredData = [[NSMutableDictionary alloc] init]; 33 | } 34 | 35 | return self; 36 | } 37 | 38 | - (void)addStructuredData:(NSDictionary*)data withID:(NSString*)sdID 39 | { 40 | [_structuredData setObject:data forKey:sdID]; 41 | } 42 | 43 | - (void)structuredDataWithDictionary:(NSDictionary*)data 44 | { 45 | if ([data isKindOfClass:[NSDictionary class]]) { 46 | 47 | _structuredData = [NSMutableDictionary dictionaryWithDictionary:data]; 48 | } 49 | } 50 | 51 | - (NSString*)composedString 52 | { 53 | NSString *returnValue = nil; 54 | 55 | if ([_structuredData count] > 0) { 56 | 57 | NSMutableArray *sdElements = [[NSMutableArray alloc] init]; 58 | 59 | [_structuredData enumerateKeysAndObjectsUsingBlock:^(id sdID, id params, BOOL *stop) { 60 | 61 | if ([sdID isKindOfClass:[NSString class]] && [params isKindOfClass:[NSDictionary class]]) { 62 | 63 | NSMutableString *sdElement = [NSMutableString stringWithFormat:@"[%@ ", sdID]; 64 | NSMutableArray *paramStrings = [[NSMutableArray alloc] init]; 65 | 66 | [params enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) { 67 | 68 | if ([key isKindOfClass:[NSString class]] && [value isKindOfClass:[NSString class]]) { 69 | 70 | NSString *cleanedKey = [self cleanedKeyWithString:key]; 71 | NSString *escapedValue = [self escapedValueWithString:value]; 72 | [paramStrings addObject:[NSString stringWithFormat:@"%@=\"%@\"", cleanedKey, escapedValue]]; 73 | } 74 | }]; 75 | 76 | [sdElement appendString:[paramStrings componentsJoinedByString:@" "]]; 77 | [sdElement appendString:@"]"]; 78 | 79 | [sdElements addObject:sdElement]; 80 | } 81 | }]; 82 | 83 | returnValue = [sdElements componentsJoinedByString:@""]; 84 | } 85 | 86 | return returnValue; 87 | } 88 | 89 | - (NSString*)escapedValueWithString:(NSString*)originalString 90 | { 91 | NSString *escapedString = [originalString stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"]; 92 | escapedString = [escapedString stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]; 93 | escapedString = [escapedString stringByReplacingOccurrencesOfString:@"]" withString:@"\\]"]; 94 | 95 | return escapedString; 96 | } 97 | 98 | - (NSString*)cleanedKeyWithString:(NSString*)originalString 99 | { 100 | NSMutableCharacterSet *invalidCharacters = [[NSMutableCharacterSet alloc] init]; 101 | [invalidCharacters addCharactersInString:@"= ]\""]; 102 | 103 | NSString *cleanedString = [[originalString componentsSeparatedByCharactersInSet:invalidCharacters] componentsJoinedByString:@""]; 104 | cleanedString = [MTSyslogMessageStructuredData cleanString:cleanedString maximumLength:32]; 105 | 106 | return cleanedString; 107 | } 108 | 109 | + (NSString*)cleanString:(NSString*)originalString maximumLength:(NSInteger)maxLength 110 | { 111 | NSString *cleanedString = nil; 112 | 113 | if (originalString) { 114 | 115 | // convert string to US-ASCII 116 | NSData *stringData = [originalString dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]; 117 | cleanedString = [[NSString alloc] initWithData:stringData encoding:NSASCIIStringEncoding]; 118 | 119 | // remove all non-prinable characters 120 | cleanedString = [cleanedString stringByReplacingOccurrencesOfString:@"[^\x21-\x7E]" 121 | withString:@"" 122 | options:NSRegularExpressionSearch 123 | range:NSMakeRange(0, [originalString length])]; 124 | 125 | // make sure the string does not exceed the allowed length 126 | if (maxLength > 0 && [cleanedString length] > maxLength) { 127 | cleanedString = [cleanedString substringToIndex:(maxLength - 1)]; 128 | } 129 | } 130 | 131 | return cleanedString; 132 | } 133 | 134 | @end 135 | -------------------------------------------------------------------------------- /source/PrivilegesAgent/Classes/MTWebhook.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTWebhook.h 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | #import "MTPrivilegesUser.h" 20 | 21 | /*! 22 | @class MTWebhook 23 | @abstract A class that provides a method to post information about a privilege change to a webhook. 24 | */ 25 | 26 | @interface MTWebhook : NSObject 27 | 28 | /*! 29 | @method init 30 | @discussion The init method is not available. Please use initWithURL: instead. 31 | */ 32 | - (instancetype)init NS_UNAVAILABLE; 33 | 34 | /*! 35 | @method initWithURL: 36 | @abstract Initialize a MTWebhook object with a given url. 37 | @param url The url of the webhook. 38 | @discussion Returns an initialized MTWebhook object or nil if an error occurred. 39 | */ 40 | - (instancetype)initWithURL:(NSURL*)url NS_DESIGNATED_INITIALIZER; 41 | 42 | /*! 43 | @method postToWebhookForUser:reason:expirationDate:completionHandler: 44 | @abstract Post data about a privilege change to the webhook. 45 | @param user The MTPrivilegesUser the privilege change belongs to. 46 | @param reason The reason for the privilege change. Might be nil. 47 | @param expiration The date the administrator privileges expire. Might be nil. 48 | @param customData An optional dictionary that is added to the webhook data. 49 | @param completionHandler The handler to call when the request is complete. 50 | @discussion The returned error object might contain error information if an error occurred or will be nil if no error occurred. 51 | */ 52 | - (void)postToWebhookForUser:(MTPrivilegesUser*)user 53 | reason:(NSString*)reason 54 | expirationDate:(NSDate*)expiration 55 | customData:(NSDictionary*)customData 56 | completionHandler:(void (^) (NSError *error))completionHandler; 57 | 58 | @end 59 | 60 | -------------------------------------------------------------------------------- /source/PrivilegesAgent/Classes/MTWebhook.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTWebhook.m 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTWebhook.h" 19 | #import "MTSystemInfo.h" 20 | #import "Constants.h" 21 | #import "MTClientCertificate.h" 22 | 23 | @interface MTWebhook () 24 | @property (nonatomic, strong, readwrite) NSURL *url; 25 | @end 26 | 27 | @implementation MTWebhook 28 | 29 | - (instancetype)initWithURL:(NSURL*)url 30 | { 31 | self = [super init]; 32 | 33 | if (self) { 34 | _url = url; 35 | } 36 | 37 | return self; 38 | } 39 | 40 | 41 | - (void)postToWebhookForUser:(MTPrivilegesUser*)user 42 | reason:(NSString*)reason 43 | expirationDate:(NSDate*)expiration 44 | customData:(NSDictionary*)customData 45 | completionHandler:(void (^) (NSError *error))completionHandler 46 | { 47 | NSString *expirationDateString = @""; 48 | NSISO8601DateFormatter *dateFormatter = [[NSISO8601DateFormatter alloc] init]; 49 | 50 | if ([user hasAdminPrivileges] && expiration) { expirationDateString = [dateFormatter stringFromDate:expiration]; } 51 | 52 | NSMutableDictionary *jsonDict = [NSMutableDictionary dictionaryWithObjectsAndKeys: 53 | [user userName], @"user", 54 | [NSNumber numberWithBool:[user hasAdminPrivileges]], @"admin", 55 | expirationDateString, @"expires", 56 | (reason) ? reason : @"", @"reason", 57 | ([user hasAdminPrivileges]) ? kMTWebhookEventTypeGranted : kMTWebhookEventTypeRevoked, @"event", 58 | [MTSystemInfo machineUUID], @"machine", 59 | [dateFormatter stringFromDate:[NSDate now]], @"timestamp", 60 | nil 61 | ]; 62 | 63 | if ([[customData allKeys] count] > 0) { [jsonDict setObject:customData forKey:@"custom_data"]; } 64 | 65 | NSError *error = nil; 66 | NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonDict 67 | options:NSJSONWritingSortedKeys 68 | error:&error 69 | ]; 70 | 71 | if (!error) { 72 | 73 | NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:_url]; 74 | [request setHTTPMethod:@"POST"]; 75 | [request setValue:@"application/json;charset=utf-8" forHTTPHeaderField:@"Content-Type"]; 76 | [request setHTTPBody:jsonData]; 77 | 78 | NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] 79 | delegate:self 80 | delegateQueue:nil 81 | ]; 82 | NSURLSessionDataTask* dataTask = [session dataTaskWithRequest:request 83 | completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { 84 | 85 | if (completionHandler) { completionHandler(error); } 86 | [session finishTasksAndInvalidate]; 87 | }]; 88 | 89 | [dataTask resume]; 90 | 91 | } else { 92 | 93 | if (completionHandler) { completionHandler(error); } 94 | } 95 | } 96 | 97 | - (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler 98 | { 99 | BOOL credentialsFound = NO; 100 | 101 | if ([[[challenge protectionSpace] authenticationMethod] isEqualToString:NSURLAuthenticationMethodClientCertificate]) { 102 | 103 | CFTypeRef items = NULL; 104 | 105 | NSDictionary *attrs = [NSDictionary dictionaryWithObjectsAndKeys: 106 | (id)kSecClassIdentity, (id)kSecClass, 107 | [NSNumber numberWithBool:YES], (id)kSecReturnRef, 108 | (id)kSecMatchLimitAll, (id)kSecMatchLimit, 109 | nil 110 | ]; 111 | 112 | OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)attrs, &items); 113 | 114 | if (status == errSecSuccess && items) { 115 | 116 | NSArray *allSecItems = CFBridgingRelease(items); 117 | 118 | for (NSData *distinguishedName in [[challenge protectionSpace] distinguishedNames]) { 119 | 120 | MTClientCertificate *clientCert = [[MTClientCertificate alloc] initWithDistinguishedName:distinguishedName]; 121 | SecIdentityRef matchingIdentityRef = [clientCert matchingIdentityWithSecItems:allSecItems]; 122 | 123 | if (matchingIdentityRef) { 124 | 125 | NSURLCredential *credential = [NSURLCredential credentialWithIdentity:matchingIdentityRef 126 | certificates:nil 127 | persistence:NSURLCredentialPersistenceForSession 128 | ]; 129 | 130 | credentialsFound = YES; 131 | completionHandler(NSURLSessionAuthChallengeUseCredential, credential); 132 | 133 | break; 134 | } 135 | } 136 | } 137 | } 138 | 139 | if (!credentialsFound) { completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil); } 140 | } 141 | 142 | @end 143 | -------------------------------------------------------------------------------- /source/PrivilegesAgent/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSAppleScriptEnabled 6 | 7 | OSAScriptingDefinition 8 | PrivilegesAgent.sdef 9 | 10 | 11 | -------------------------------------------------------------------------------- /source/PrivilegesAgent/PrivilegesAgent-ParentConstraint.coderequirement: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | is-init-proc 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /source/PrivilegesAgent/PrivilegesAgent-SelfConstraint.coderequirement: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | $or-array 6 | 7 | 8 | $or 9 | 10 | launch-type 11 | 12 | $lt 13 | 3 14 | 15 | 16 | 17 | 18 | $or 19 | 20 | launch-type 21 | 22 | $gt 23 | 3 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /source/PrivilegesAgent/PrivilegesAgent.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.application-groups 6 | 7 | $(TeamIdentifierPrefix)corp.sap.privileges 8 | 9 | com.apple.security.automation.apple-events 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /source/PrivilegesAgent/PrivilegesAgent.sdef: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /source/PrivilegesAgent/PrivilegesAgentProtocol.h: -------------------------------------------------------------------------------- 1 | /* 2 | PrivilegesAgentProtocol.h 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | /*! 21 | @protocol PrivilegesAgentProtocol 22 | @abstract Defines the protocol implemented by the agent.. 23 | */ 24 | 25 | @protocol PrivilegesAgentProtocol 26 | 27 | /*! 28 | @method connectWithEndpointReply: 29 | @abstract Returns an endpoint that's connected to the daemon. 30 | @param reply The reply block to call when the request is complete. 31 | @discussion This method is only called by the xpc service. 32 | */ 33 | - (void)connectWithEndpointReply:(void (^)(NSXPCListenerEndpoint* endpoint))reply; 34 | 35 | /*! 36 | @method requestAdminRightsWithReason:completionHandler: 37 | @abstract Request administrator privileges for the current user. 38 | @param reason A string containing the reason the user requests administrator privileges. May be nil. 39 | @param completionHandler The handler to call when the request is complete. 40 | @discussion Returns YES if the operation was successful, otherwise returns NO. 41 | */ 42 | - (void)requestAdminRightsWithReason:(NSString*)reason completionHandler:(void(^)(BOOL success))completionHandler; 43 | 44 | /*! 45 | @method revokeAdminPrivilegesWithCompletionHandler: 46 | @abstract Revoke administrator privileges for the current user. 47 | @param completionHandler The handler to call when the request is complete. 48 | @discussion Returns YES if the operation was successful, otherwise returns NO. 49 | */ 50 | - (void)revokeAdminRightsWithCompletionHandler:(void(^)(BOOL success))completionHandler; 51 | 52 | /*! 53 | @method renewAdminRightsWithCompletionHandler: 54 | @abstract Renew expiring administrator privileges for the current user. 55 | @param completionHandler The handler to call when the request is complete. 56 | @discussion Returns YES if the operation was successful, otherwise returns NO. 57 | */ 58 | - (void)renewAdminRightsWithCompletionHandler:(void(^)(BOOL success))completionHandler; 59 | 60 | /*! 61 | @method authenticateUserWithCompletionHandler: 62 | @param completionHandler The reply block to call when the request is complete. 63 | */ 64 | - (void)authenticateUserWithCompletionHandler:(void(^)(BOOL success))completionHandler; 65 | 66 | /*! 67 | @method expirationWithReply: 68 | @abstract Get the date when the current user's administrator privileges expire. 69 | @param reply The reply block to call when the request is complete. 70 | @discussion Returns the expiration date and the number of minutes remaining. Expiration date will be nil 71 | if the administrator privileges are already expired. 72 | */ 73 | - (void)expirationWithReply:(void(^)(NSDate *expires, NSUInteger remaining))reply; 74 | 75 | /*! 76 | @method isExecutableFileAtURL:reply: 77 | @abstract Get whether the current user can execute the file at the given url. 78 | @param reply The reply block to call when the request is complete. 79 | @discussion Returns YES if the file can be executed by the current user, otherwise returns NO. 80 | */ 81 | - (void)isExecutableFileAtURL:(NSURL*)url reply:(void(^)(BOOL isExecutable))reply; 82 | 83 | @end 84 | -------------------------------------------------------------------------------- /source/PrivilegesAgent/StatusItem.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /source/PrivilegesAgent/StatusItem.xcassets/locked.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "locked-16.png", 5 | "idiom" : "mac", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "locked-32.png", 10 | "idiom" : "mac", 11 | "scale" : "2x" 12 | } 13 | ], 14 | "info" : { 15 | "author" : "xcode", 16 | "version" : 1 17 | }, 18 | "properties" : { 19 | "template-rendering-intent" : "template" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /source/PrivilegesAgent/StatusItem.xcassets/locked.imageset/locked-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/source/PrivilegesAgent/StatusItem.xcassets/locked.imageset/locked-16.png -------------------------------------------------------------------------------- /source/PrivilegesAgent/StatusItem.xcassets/locked.imageset/locked-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/source/PrivilegesAgent/StatusItem.xcassets/locked.imageset/locked-32.png -------------------------------------------------------------------------------- /source/PrivilegesAgent/StatusItem.xcassets/locked_managed.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "locked_managed-16.png", 5 | "idiom" : "mac", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "locked_managed-32.png", 10 | "idiom" : "mac", 11 | "scale" : "2x" 12 | } 13 | ], 14 | "info" : { 15 | "author" : "xcode", 16 | "version" : 1 17 | }, 18 | "properties" : { 19 | "template-rendering-intent" : "template" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /source/PrivilegesAgent/StatusItem.xcassets/locked_managed.imageset/locked_managed-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/source/PrivilegesAgent/StatusItem.xcassets/locked_managed.imageset/locked_managed-16.png -------------------------------------------------------------------------------- /source/PrivilegesAgent/StatusItem.xcassets/locked_managed.imageset/locked_managed-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/source/PrivilegesAgent/StatusItem.xcassets/locked_managed.imageset/locked_managed-32.png -------------------------------------------------------------------------------- /source/PrivilegesAgent/StatusItem.xcassets/unlocked.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "unlocked-16.png", 5 | "idiom" : "mac", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "unlocked-32.png", 10 | "idiom" : "mac", 11 | "scale" : "2x" 12 | } 13 | ], 14 | "info" : { 15 | "author" : "xcode", 16 | "version" : 1 17 | }, 18 | "properties" : { 19 | "template-rendering-intent" : "template" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /source/PrivilegesAgent/StatusItem.xcassets/unlocked.imageset/unlocked-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/source/PrivilegesAgent/StatusItem.xcassets/unlocked.imageset/unlocked-16.png -------------------------------------------------------------------------------- /source/PrivilegesAgent/StatusItem.xcassets/unlocked.imageset/unlocked-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/source/PrivilegesAgent/StatusItem.xcassets/unlocked.imageset/unlocked-32.png -------------------------------------------------------------------------------- /source/PrivilegesAgent/StatusItem.xcassets/unlocked_managed.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "unlocked_managed-16.png", 5 | "idiom" : "mac", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "unlocked_managed-32.png", 10 | "idiom" : "mac", 11 | "scale" : "2x" 12 | } 13 | ], 14 | "info" : { 15 | "author" : "xcode", 16 | "version" : 1 17 | }, 18 | "properties" : { 19 | "template-rendering-intent" : "template" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /source/PrivilegesAgent/StatusItem.xcassets/unlocked_managed.imageset/unlocked_managed-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/source/PrivilegesAgent/StatusItem.xcassets/unlocked_managed.imageset/unlocked_managed-16.png -------------------------------------------------------------------------------- /source/PrivilegesAgent/StatusItem.xcassets/unlocked_managed.imageset/unlocked_managed-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/source/PrivilegesAgent/StatusItem.xcassets/unlocked_managed.imageset/unlocked_managed-32.png -------------------------------------------------------------------------------- /source/PrivilegesAgent/main.m: -------------------------------------------------------------------------------- 1 | /* 2 | main.m 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | int main(int argc, const char * argv[]) 21 | { 22 | return NSApplicationMain(argc, argv); 23 | } 24 | -------------------------------------------------------------------------------- /source/PrivilegesCLI/Classes/MTProcessInfo.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTProcessInfo.h 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | /*! 21 | @class MTProcessInfo 22 | @abstract A class that provides methods to access the relevant command line arguments. 23 | */ 24 | 25 | @interface MTProcessInfo : NSProcessInfo 26 | 27 | /*! 28 | @method showStatus 29 | @abstract Get whether the status should be displayed. 30 | @discussion Returns YES if the status should be displayed, otherwise returns NO. 31 | */ 32 | - (BOOL)showStatus; 33 | 34 | /*! 35 | @method showVersion 36 | @abstract Get whether the version should be displayed. 37 | @discussion Returns YES if the version should be displayed, otherwise returns NO. 38 | */ 39 | - (BOOL)showVersion; 40 | 41 | /*! 42 | @method requestPrivileges 43 | @abstract Get whether administrator privileges were requested. 44 | @discussion Returns YES if administrator privileges were requested, otherwise returns NO. 45 | */ 46 | - (BOOL)requestPrivileges; 47 | 48 | /*! 49 | @method revertPrivileges 50 | @abstract Get whether administrator privileges should be reverted. 51 | @discussion Returns YES if administrator privileges should be reverted, otherwise returns NO. 52 | */ 53 | - (BOOL)revertPrivileges; 54 | 55 | /*! 56 | @method launchURL 57 | @abstract Get the launch url of the current process. 58 | @discussion Returns an NSURL object or nil, if an error occurred. 59 | */ 60 | - (NSURL*)launchURL; 61 | 62 | /*! 63 | @method requestReason 64 | @abstract Get the reason the user provided to get administator privileges. 65 | @discussion Returns a NSString object containing the provided reason. Returns nil if no reason has been provided. 66 | */ 67 | - (NSString*)requestReason; 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /source/PrivilegesCLI/Classes/MTProcessInfo.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTProcessInfo.m 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTProcessInfo.h" 19 | 20 | @implementation MTProcessInfo 21 | 22 | - (BOOL)showStatus 23 | { 24 | BOOL show = [[self arguments] containsObject:@"-s"] || [[self arguments] containsObject:@"--status"]; 25 | return show; 26 | } 27 | 28 | - (BOOL)requestPrivileges 29 | { 30 | BOOL request = [[self arguments] containsObject:@"-a"] || [[self arguments] containsObject:@"--add"]; 31 | return request; 32 | } 33 | 34 | - (BOOL)revertPrivileges 35 | { 36 | BOOL revert = [[self arguments] containsObject:@"-r"] || [[self arguments] containsObject:@"--remove"]; 37 | return revert; 38 | } 39 | 40 | - (BOOL)showVersion 41 | { 42 | BOOL show = [[self arguments] containsObject:@"-v"] || [[self arguments] containsObject:@"--version"]; 43 | return show; 44 | } 45 | 46 | - (NSURL*)launchURL 47 | { 48 | NSURL *url = nil; 49 | 50 | NSString *launchPath = [[self arguments] firstObject]; 51 | if (launchPath) { url = [NSURL fileURLWithPath:launchPath]; } 52 | 53 | return url; 54 | } 55 | 56 | - (NSString *)requestReason 57 | { 58 | NSString *reason = nil; 59 | 60 | NSInteger index = [[self arguments] indexOfObject:@"-n"]; 61 | if (index == NSNotFound) { index = [[self arguments] indexOfObject:@"--reason"]; } 62 | 63 | if (index != NSNotFound && index + 1 < [[self arguments] count]) { 64 | 65 | reason = [[self arguments] objectAtIndex:index + 1]; 66 | } 67 | 68 | return reason; 69 | } 70 | 71 | @end 72 | -------------------------------------------------------------------------------- /source/PrivilegesCLI/PrivilegesCLI-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleIdentifier 6 | corp.sap.privileges.cli 7 | CFBundleInfoDictionaryVersion 8 | 6.0 9 | CFBundleName 10 | PrivilegesCLI 11 | CFBundleShortVersionString 12 | $(MARKETING_VERSION) 13 | CFBundleVersion 14 | $(CURRENT_PROJECT_VERSION) 15 | NSHumanReadableCopyright 16 | © 2016-2025 SAP SE. All rights reserved. 17 | 18 | 19 | -------------------------------------------------------------------------------- /source/PrivilegesCLI/PrivilegesCLI.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.application-groups 6 | 7 | $(TeamIdentifierPrefix)corp.sap.privileges 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /source/PrivilegesDaemon/Classes/MTPrivilegesDaemon.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTPrivilegesDaemon.h 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | #import "PrivilegesDaemonProtocol.h" 20 | 21 | @interface MTPrivilegesDaemon : NSObject 22 | 23 | /*! 24 | @method invalidateXPC 25 | @abstract Invalidates all connections to the daemon. 26 | */ 27 | - (void)invalidateXPC; 28 | 29 | /*! 30 | @method numberOfActiveXPCConnections 31 | @abstract Get the number of connections currently open to the daemon. 32 | */ 33 | - (NSInteger)numberOfActiveXPCConnections; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /source/PrivilegesDaemon/PrivilegesDaemon-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleIdentifier 6 | corp.sap.privileges.daemon 7 | CFBundleInfoDictionaryVersion 8 | 6.0 9 | CFBundleName 10 | PrivilegesDaemon 11 | CFBundleShortVersionString 12 | $(MARKETING_VERSION) 13 | CFBundleVersion 14 | $(CURRENT_PROJECT_VERSION) 15 | NSHumanReadableCopyright 16 | © 2025 SAP SE. All rights reserved. 17 | 18 | 19 | -------------------------------------------------------------------------------- /source/PrivilegesDaemon/PrivilegesDaemon-ParentConstraint.coderequirement: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | is-init-proc 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /source/PrivilegesDaemon/PrivilegesDaemon-SelfConstraint.coderequirement: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | $or-array 6 | 7 | 8 | $or 9 | 10 | launch-type 11 | 12 | $lt 13 | 3 14 | 15 | 16 | 17 | 18 | $or 19 | 20 | launch-type 21 | 22 | $gt 23 | 3 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /source/PrivilegesDaemon/PrivilegesDaemonProtocol.h: -------------------------------------------------------------------------------- 1 | /* 2 | PrivilegesDaemonProtocol.h 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | #import 20 | 21 | /*! 22 | @protocol PrivilegesDaemonProtocol 23 | @abstract Defines the protocol implemented by the daemon and called by the xpc service and Privileges. 24 | */ 25 | 26 | @protocol PrivilegesDaemonProtocol 27 | 28 | /*! 29 | @method grantAdminRightsToUser:reason:completionHandler: 30 | @abstract Grant administrator privileges to the given user. 31 | @param userName A string containing the user name. 32 | @param reason A string containing the reason the user requests administrator privileges. May be nil. 33 | @param completionHandler The handler to call when the request is complete. 34 | @discussion Returns YES if adminstrator privileges were successfully granted, otherwise returns NO. 35 | */ 36 | - (void)grantAdminRightsToUser:(NSString*)userName 37 | reason:(NSString*)reason 38 | completionHandler:(void(^)(BOOL success))completionHandler; 39 | 40 | /*! 41 | @method removeAdminRightsFromUser:reason:completionHandler: 42 | @abstract Remove administrator privileges from the current user. 43 | @param userName A string containing the user name. 44 | @param reason A string containing the reason the user requests administrator privileges. May be nil. 45 | @param completionHandler The handler to call when the request is complete. 46 | @discussion Returns YES if adminstrator privileges were successfully removed, otherwise returns NO. 47 | */ 48 | - (void)removeAdminRightsFromUser:(NSString*)userName 49 | reason:(NSString*)reason 50 | completionHandler:(void(^)(BOOL success))completionHandler; 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /source/PrivilegesDaemon/main.m: -------------------------------------------------------------------------------- 1 | /* 2 | main.m 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | #import "MTPrivilegesDaemon.h" 20 | #import "Constants.h" 21 | 22 | @interface Main : NSObject 23 | @property (nonatomic, strong, readwrite) MTPrivilegesDaemon *privilegesDaemon; 24 | @property (assign) BOOL shouldTerminate; 25 | @end 26 | 27 | @implementation Main 28 | 29 | - (void)run 30 | { 31 | os_log(OS_LOG_DEFAULT, "SAPCorp: Starting"); 32 | 33 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(30 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 34 | 35 | self->_shouldTerminate = YES; 36 | }); 37 | 38 | while (!_shouldTerminate || [_privilegesDaemon numberOfActiveXPCConnections] > 0) { 39 | 40 | [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:60]]; 41 | } 42 | 43 | [_privilegesDaemon invalidateXPC]; 44 | os_log(OS_LOG_DEFAULT, "SAPCorp: Exiting"); 45 | } 46 | 47 | @end 48 | 49 | 50 | int main(int argc, const char * argv[]) 51 | { 52 | #pragma unused(argc) 53 | #pragma unused(argv) 54 | 55 | @autoreleasepool { 56 | 57 | Main *m = [[Main alloc] init]; 58 | m.privilegesDaemon = [[MTPrivilegesDaemon alloc] init]; 59 | [m run]; 60 | } 61 | 62 | return EXIT_SUCCESS; 63 | } 64 | -------------------------------------------------------------------------------- /source/PrivilegesTile/AppIcons-Beta.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /source/PrivilegesTile/AppIcons-Beta.xcassets/locked.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "locked.png", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /source/PrivilegesTile/AppIcons-Beta.xcassets/locked.imageset/locked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/source/PrivilegesTile/AppIcons-Beta.xcassets/locked.imageset/locked.png -------------------------------------------------------------------------------- /source/PrivilegesTile/AppIcons-Beta.xcassets/locked_managed.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "locked_managed.png", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /source/PrivilegesTile/AppIcons-Beta.xcassets/locked_managed.imageset/locked_managed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/source/PrivilegesTile/AppIcons-Beta.xcassets/locked_managed.imageset/locked_managed.png -------------------------------------------------------------------------------- /source/PrivilegesTile/AppIcons-Beta.xcassets/unlocked.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "unlocked.png", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /source/PrivilegesTile/AppIcons-Beta.xcassets/unlocked.imageset/unlocked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/source/PrivilegesTile/AppIcons-Beta.xcassets/unlocked.imageset/unlocked.png -------------------------------------------------------------------------------- /source/PrivilegesTile/AppIcons-Beta.xcassets/unlocked_managed.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "unlocked_managed.png", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /source/PrivilegesTile/AppIcons-Beta.xcassets/unlocked_managed.imageset/unlocked_managed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/source/PrivilegesTile/AppIcons-Beta.xcassets/unlocked_managed.imageset/unlocked_managed.png -------------------------------------------------------------------------------- /source/PrivilegesTile/AppIcons.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /source/PrivilegesTile/AppIcons.xcassets/locked.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "locked.png", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /source/PrivilegesTile/AppIcons.xcassets/locked.imageset/locked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/source/PrivilegesTile/AppIcons.xcassets/locked.imageset/locked.png -------------------------------------------------------------------------------- /source/PrivilegesTile/AppIcons.xcassets/locked_managed.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "locked_managed.png", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /source/PrivilegesTile/AppIcons.xcassets/locked_managed.imageset/locked_managed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/source/PrivilegesTile/AppIcons.xcassets/locked_managed.imageset/locked_managed.png -------------------------------------------------------------------------------- /source/PrivilegesTile/AppIcons.xcassets/unlocked.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "unlocked.png", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /source/PrivilegesTile/AppIcons.xcassets/unlocked.imageset/unlocked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/source/PrivilegesTile/AppIcons.xcassets/unlocked.imageset/unlocked.png -------------------------------------------------------------------------------- /source/PrivilegesTile/AppIcons.xcassets/unlocked_managed.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "unlocked_managed.png", 5 | "idiom" : "universal" 6 | } 7 | ], 8 | "info" : { 9 | "author" : "xcode", 10 | "version" : 1 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /source/PrivilegesTile/AppIcons.xcassets/unlocked_managed.imageset/unlocked_managed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/source/PrivilegesTile/AppIcons.xcassets/unlocked_managed.imageset/unlocked_managed.png -------------------------------------------------------------------------------- /source/PrivilegesTile/Classes/PrivilegesTile.h: -------------------------------------------------------------------------------- 1 | /* 2 | PrivilegesTile.h 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | @interface PrivilegesTile : NSObject 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /source/PrivilegesWatcher/PrivilegesWatcher-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleIdentifier 6 | corp.sap.privileges.watcher 7 | CFBundleInfoDictionaryVersion 8 | 6.0 9 | CFBundleName 10 | PrivilegesWatcher 11 | CFBundleShortVersionString 12 | $(MARKETING_VERSION) 13 | CFBundleVersion 14 | $(CURRENT_PROJECT_VERSION) 15 | NSHumanReadableCopyright 16 | © 2016-2025 SAP SE. All rights reserved. 17 | 18 | 19 | -------------------------------------------------------------------------------- /source/PrivilegesWatcher/PrivilegesWatcher-ParentConstraint.coderequirement: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | is-init-proc 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /source/PrivilegesWatcher/PrivilegesWatcher-SelfConstraint.coderequirement: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | $or-array 6 | 7 | 8 | $or 9 | 10 | launch-type 11 | 12 | $lt 13 | 3 14 | 15 | 16 | 17 | 18 | $or 19 | 20 | launch-type 21 | 22 | $gt 23 | 3 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /source/PrivilegesWatcher/main.m: -------------------------------------------------------------------------------- 1 | /* 2 | main.m 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | #import "Constants.h" 20 | #import 21 | 22 | @protocol PrivilegesWatcherDelegate 23 | - (void)postNotification; 24 | @end 25 | 26 | void fsevents_callback(ConstFSEventStreamRef streamRef, void *clientCallBackInfo, size_t numEvents, void *eventPaths, const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[]) 27 | { 28 | char **paths = eventPaths; 29 | id myDelegate = (__bridge id)clientCallBackInfo; 30 | 31 | if (myDelegate) { 32 | 33 | for (int i = 0; i < numEvents; i++) { 34 | 35 | NSString *eventPath = [NSString stringWithUTF8String:paths[i]]; 36 | 37 | if ([[eventPath lastPathComponent] isEqualToString:@"admin.plist"]) { 38 | 39 | dispatch_async(dispatch_get_main_queue(), ^{ [myDelegate postNotification]; }); 40 | break; 41 | } 42 | } 43 | } 44 | } 45 | 46 | @interface Main : NSObject 47 | @property (nonatomic, strong, readwrite) NSTimer *delayTimer; 48 | @property (nonatomic, strong, readwrite) NSTimer *terminationTimer; 49 | @property (assign) BOOL shouldTerminate; 50 | @end 51 | 52 | @implementation Main 53 | 54 | - (void)run 55 | { 56 | os_log(OS_LOG_DEFAULT, "SAPCorp: Starting"); 57 | 58 | [self scheduleTerminationTimer]; 59 | 60 | // post a notification so the PrivilegesAgent knows about the change 61 | [self postNotification]; 62 | 63 | // monitor the admin group for further changes 64 | NSString *basePath = @"/var/db/dslocal/nodes/Default/groups"; 65 | NSArray *pathsToWatch = [NSArray arrayWithObject:basePath]; 66 | FSEventStreamContext cntxt = {0, (__bridge void *)(self), NULL, NULL, NULL}; 67 | dispatch_queue_t queue = dispatch_queue_create("corp.sap.privileges.watcher.queue", DISPATCH_QUEUE_SERIAL); 68 | 69 | FSEventStreamRef stream = FSEventStreamCreate( 70 | NULL, 71 | &fsevents_callback, 72 | &cntxt, 73 | (__bridge CFArrayRef)pathsToWatch, 74 | kFSEventStreamEventIdSinceNow, 75 | 0.1, 76 | kFSEventStreamCreateFlagFileEvents 77 | ); 78 | 79 | if (stream) { 80 | 81 | FSEventStreamSetDispatchQueue(stream, queue); 82 | FSEventStreamStart(stream); 83 | } 84 | 85 | while (!_shouldTerminate) { 86 | 87 | [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:60]]; 88 | } 89 | 90 | if (stream) { 91 | 92 | FSEventStreamStop(stream); 93 | FSEventStreamRelease(stream); 94 | } 95 | 96 | os_log(OS_LOG_DEFAULT, "SAPCorp: Exiting"); 97 | } 98 | 99 | - (void)scheduleTerminationTimer 100 | { 101 | if (_terminationTimer) { 102 | [_terminationTimer invalidate]; 103 | _terminationTimer = nil; 104 | }; 105 | 106 | _terminationTimer = [NSTimer scheduledTimerWithTimeInterval:30 107 | repeats:YES 108 | block:^(NSTimer *timer) { 109 | self->_shouldTerminate = YES; 110 | }]; 111 | } 112 | 113 | - (void)postNotification 114 | { 115 | [[NSDistributedNotificationCenter defaultCenter] postNotificationName:kMTNotificationNameAdminGroupDidChange 116 | object:nil 117 | userInfo:nil 118 | options:NSNotificationDeliverImmediately | NSNotificationPostToAllSessions 119 | ]; 120 | 121 | [self scheduleTerminationTimer]; 122 | } 123 | 124 | @end 125 | 126 | int main(int argc, const char * argv[]) 127 | { 128 | #pragma unused(argc) 129 | #pragma unused(argv) 130 | 131 | @autoreleasepool { 132 | 133 | Main *m = [[Main alloc] init]; 134 | [m run]; 135 | } 136 | 137 | return 0; 138 | } 139 | -------------------------------------------------------------------------------- /source/PrivilegesXPC/Classes/PrivilegesXPC.h: -------------------------------------------------------------------------------- 1 | /* 2 | PrivilegesXPC.h 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | #import "PrivilegesXPCProtocol.h" 20 | 21 | @interface PrivilegesXPC : NSObject 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /source/PrivilegesXPC/Classes/PrivilegesXPC.m: -------------------------------------------------------------------------------- 1 | /* 2 | PrivilegesXPC.m 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "PrivilegesXPC.h" 19 | #import "MTAgentConnection.h" 20 | #import 21 | 22 | @interface PrivilegesXPC () 23 | @property (nonatomic, strong, readwrite) MTAgentConnection *agentConnection; 24 | @end 25 | 26 | @implementation PrivilegesXPC 27 | 28 | - (void)connectWithAgentEndpointReply:(void(^)(NSXPCListenerEndpoint *endpoint))reply 29 | { 30 | if (!_agentConnection) { _agentConnection = [[MTAgentConnection alloc] init]; } 31 | 32 | [_agentConnection connectToAgentWithExportedObject:nil 33 | andExecuteCommandBlock:^{ 34 | 35 | [[[self->_agentConnection connection] remoteObjectProxyWithErrorHandler:^(NSError *error) { 36 | 37 | os_log_with_type(OS_LOG_DEFAULT, OS_LOG_TYPE_FAULT, "SAPCorp: Failed to connect to agent: %{public}@", error); 38 | 39 | }] connectWithEndpointReply:^(NSXPCListenerEndpoint *endpoint) { 40 | 41 | reply(endpoint); 42 | }]; 43 | }]; 44 | } 45 | 46 | - (void)dealloc 47 | { 48 | if (_agentConnection) { [_agentConnection invalidate]; } 49 | } 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /source/PrivilegesXPC/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | XPCService 6 | 7 | ServiceType 8 | Application 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /source/PrivilegesXPC/PrivilegesXPC-ParentConstraint.coderequirement: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | is-init-proc 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /source/PrivilegesXPC/PrivilegesXPC-ResponsibleConstraint.coderequirement: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | team-identifier 6 | 7R5ZEU67FQ 7 | signing-identifier 8 | corp.sap.privileges 9 | 10 | 11 | -------------------------------------------------------------------------------- /source/PrivilegesXPC/PrivilegesXPC.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /source/PrivilegesXPC/PrivilegesXPCProtocol.h: -------------------------------------------------------------------------------- 1 | /* 2 | PrivilegesXPCProtocol.h 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | /*! 21 | @protocol PrivilegesXPCProtocol 22 | @abstract Defines the protocol implemented by the xpc service and 23 | called by Privileges. 24 | */ 25 | 26 | @protocol PrivilegesXPCProtocol 27 | 28 | /*! 29 | @method connectWithAgentEndpointReply: 30 | @abstract Returns an endpoint that's connected to the agent. 31 | @param reply The reply block to call when the request is complete. 32 | */ 33 | - (void)connectWithAgentEndpointReply:(void(^)(NSXPCListenerEndpoint *endpoint))reply; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /source/PrivilegesXPC/main.m: -------------------------------------------------------------------------------- 1 | /* 2 | main.m 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | #import "PrivilegesXPC.h" 20 | #import "MTCodeSigning.h" 21 | #import 22 | 23 | @interface ServiceDelegate : NSObject 24 | @end 25 | 26 | @interface ExtendedNSXPCConnection : NSXPCConnection 27 | @property audit_token_t auditToken; 28 | @end 29 | 30 | OSStatus SecTaskValidateForRequirement(SecTaskRef task, CFStringRef requirement); 31 | 32 | @implementation ServiceDelegate 33 | 34 | - (BOOL)listener:(NSXPCListener *)listener shouldAcceptNewConnection:(NSXPCConnection *)newConnection 35 | { 36 | BOOL acceptConnection = NO; 37 | 38 | // see how we have been signed and make sure only processes with the same signing authority can connect. 39 | // additionally the calling application must have the same version number as this xpc service and must be 40 | // one of the components using a bundle identifier starting with "corp.sap.privileges" 41 | NSError *error = nil; 42 | NSString *signingAuth = [MTCodeSigning getSigningAuthorityWithError:&error]; 43 | NSString *requiredVersion = [[NSBundle bundleForClass:[self class]] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; 44 | 45 | if (signingAuth) { 46 | 47 | NSString *reqString = [MTCodeSigning codeSigningRequirementsWithCommonName:signingAuth 48 | bundleIdentifier:@"corp.sap.privileges*" 49 | versionString:requiredVersion 50 | ]; 51 | SecTaskRef taskRef = SecTaskCreateWithAuditToken(NULL, ((ExtendedNSXPCConnection*)newConnection).auditToken); 52 | 53 | if (taskRef) { 54 | 55 | if (SecTaskValidateForRequirement(taskRef, (__bridge CFStringRef)(reqString)) == errSecSuccess) { 56 | 57 | acceptConnection = YES; 58 | 59 | newConnection.exportedInterface = [NSXPCInterface interfaceWithProtocol:@protocol(PrivilegesXPCProtocol)]; 60 | PrivilegesXPC *exportedObject = [PrivilegesXPC new]; 61 | newConnection.exportedObject = exportedObject; 62 | #pragma clang diagnostic push 63 | #pragma clang diagnostic ignored "-Warc-retain-cycles" 64 | [newConnection setInvalidationHandler:^{ 65 | 66 | [newConnection setInvalidationHandler:nil]; 67 | dispatch_async(dispatch_get_main_queue(), ^{ 68 | os_log(OS_LOG_DEFAULT, "SAPCorp: %{public}@ invalidated", newConnection); 69 | }); 70 | }]; 71 | #pragma clang diagnostic pop 72 | 73 | [newConnection resume]; 74 | 75 | dispatch_async(dispatch_get_main_queue(), ^{ 76 | os_log(OS_LOG_DEFAULT, "SAPCorp: %{public}@ established", newConnection); 77 | }); 78 | 79 | } else { 80 | os_log_with_type(OS_LOG_DEFAULT, OS_LOG_TYPE_ERROR, "SAPCorp: Code signature verification failed"); 81 | } 82 | 83 | CFRelease(taskRef); 84 | } 85 | 86 | } else { 87 | os_log_with_type(OS_LOG_DEFAULT, OS_LOG_TYPE_ERROR, "SAPCorp: Failed to get code signature: %{public}@", error); 88 | } 89 | 90 | return acceptConnection; 91 | } 92 | 93 | @end 94 | 95 | int main(int argc, const char *argv[]) 96 | { 97 | // Create the delegate for the service. 98 | ServiceDelegate *delegate = [ServiceDelegate new]; 99 | 100 | // Set up the one NSXPCListener for this service. It will handle all incoming connections. 101 | NSXPCListener *listener = [NSXPCListener serviceListener]; 102 | listener.delegate = delegate; 103 | 104 | // Resuming the serviceListener starts this service. This method does not return. 105 | [listener resume]; 106 | 107 | return 0; 108 | } 109 | -------------------------------------------------------------------------------- /source/Shared/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "211", 9 | "green" : "143", 10 | "red" : "0" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | }, 15 | { 16 | "appearances" : [ 17 | { 18 | "appearance" : "luminosity", 19 | "value" : "dark" 20 | } 21 | ], 22 | "color" : { 23 | "color-space" : "srgb", 24 | "components" : { 25 | "alpha" : "1.000", 26 | "blue" : "1.000", 27 | "green" : "0.667", 28 | "red" : "0.059" 29 | } 30 | }, 31 | "idiom" : "universal" 32 | } 33 | ], 34 | "info" : { 35 | "author" : "xcode", 36 | "version" : 1 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /source/Shared/Assets.xcassets/AppIcon-Beta.appiconset/AppIcon-Beta-1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/source/Shared/Assets.xcassets/AppIcon-Beta.appiconset/AppIcon-Beta-1024.png -------------------------------------------------------------------------------- /source/Shared/Assets.xcassets/AppIcon-Beta.appiconset/AppIcon-Beta-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/source/Shared/Assets.xcassets/AppIcon-Beta.appiconset/AppIcon-Beta-128.png -------------------------------------------------------------------------------- /source/Shared/Assets.xcassets/AppIcon-Beta.appiconset/AppIcon-Beta-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/source/Shared/Assets.xcassets/AppIcon-Beta.appiconset/AppIcon-Beta-16.png -------------------------------------------------------------------------------- /source/Shared/Assets.xcassets/AppIcon-Beta.appiconset/AppIcon-Beta-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/source/Shared/Assets.xcassets/AppIcon-Beta.appiconset/AppIcon-Beta-256.png -------------------------------------------------------------------------------- /source/Shared/Assets.xcassets/AppIcon-Beta.appiconset/AppIcon-Beta-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/source/Shared/Assets.xcassets/AppIcon-Beta.appiconset/AppIcon-Beta-32.png -------------------------------------------------------------------------------- /source/Shared/Assets.xcassets/AppIcon-Beta.appiconset/AppIcon-Beta-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/source/Shared/Assets.xcassets/AppIcon-Beta.appiconset/AppIcon-Beta-512.png -------------------------------------------------------------------------------- /source/Shared/Assets.xcassets/AppIcon-Beta.appiconset/AppIcon-Beta-64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/source/Shared/Assets.xcassets/AppIcon-Beta.appiconset/AppIcon-Beta-64.png -------------------------------------------------------------------------------- /source/Shared/Assets.xcassets/AppIcon-Beta.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "AppIcon-Beta-16.png", 5 | "idiom" : "mac", 6 | "scale" : "1x", 7 | "size" : "16x16" 8 | }, 9 | { 10 | "filename" : "AppIcon-Beta-32.png", 11 | "idiom" : "mac", 12 | "scale" : "2x", 13 | "size" : "16x16" 14 | }, 15 | { 16 | "filename" : "AppIcon-Beta-32.png", 17 | "idiom" : "mac", 18 | "scale" : "1x", 19 | "size" : "32x32" 20 | }, 21 | { 22 | "filename" : "AppIcon-Beta-64.png", 23 | "idiom" : "mac", 24 | "scale" : "2x", 25 | "size" : "32x32" 26 | }, 27 | { 28 | "filename" : "AppIcon-Beta-128.png", 29 | "idiom" : "mac", 30 | "scale" : "1x", 31 | "size" : "128x128" 32 | }, 33 | { 34 | "filename" : "AppIcon-Beta-256.png", 35 | "idiom" : "mac", 36 | "scale" : "2x", 37 | "size" : "128x128" 38 | }, 39 | { 40 | "filename" : "AppIcon-Beta-256.png", 41 | "idiom" : "mac", 42 | "scale" : "1x", 43 | "size" : "256x256" 44 | }, 45 | { 46 | "filename" : "AppIcon-Beta-512.png", 47 | "idiom" : "mac", 48 | "scale" : "2x", 49 | "size" : "256x256" 50 | }, 51 | { 52 | "filename" : "AppIcon-Beta-512.png", 53 | "idiom" : "mac", 54 | "scale" : "1x", 55 | "size" : "512x512" 56 | }, 57 | { 58 | "filename" : "AppIcon-Beta-1024.png", 59 | "idiom" : "mac", 60 | "scale" : "2x", 61 | "size" : "512x512" 62 | } 63 | ], 64 | "info" : { 65 | "author" : "xcode", 66 | "version" : 1 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /source/Shared/Assets.xcassets/AppIcon.appiconset/AppIcon-1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/source/Shared/Assets.xcassets/AppIcon.appiconset/AppIcon-1024.png -------------------------------------------------------------------------------- /source/Shared/Assets.xcassets/AppIcon.appiconset/AppIcon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/source/Shared/Assets.xcassets/AppIcon.appiconset/AppIcon-128.png -------------------------------------------------------------------------------- /source/Shared/Assets.xcassets/AppIcon.appiconset/AppIcon-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/source/Shared/Assets.xcassets/AppIcon.appiconset/AppIcon-16.png -------------------------------------------------------------------------------- /source/Shared/Assets.xcassets/AppIcon.appiconset/AppIcon-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/source/Shared/Assets.xcassets/AppIcon.appiconset/AppIcon-256.png -------------------------------------------------------------------------------- /source/Shared/Assets.xcassets/AppIcon.appiconset/AppIcon-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/source/Shared/Assets.xcassets/AppIcon.appiconset/AppIcon-32.png -------------------------------------------------------------------------------- /source/Shared/Assets.xcassets/AppIcon.appiconset/AppIcon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/source/Shared/Assets.xcassets/AppIcon.appiconset/AppIcon-512.png -------------------------------------------------------------------------------- /source/Shared/Assets.xcassets/AppIcon.appiconset/AppIcon-64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SAP/macOS-enterprise-privileges/608e9e7af7fc1c05f509524f1329e49e82e3f999/source/Shared/Assets.xcassets/AppIcon.appiconset/AppIcon-64.png -------------------------------------------------------------------------------- /source/Shared/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "AppIcon-16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "AppIcon-32.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "AppIcon-32.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "AppIcon-64.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "AppIcon-128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "AppIcon-256.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "AppIcon-256.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "AppIcon-512.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "AppIcon-512.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "AppIcon-1024.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /source/Shared/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /source/Shared/Classes/MTAgentConnection.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTAgentConnection.h 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | #import "PrivilegesXPCProtocol.h" 20 | #import "PrivilegesAgentProtocol.h" 21 | #import 22 | #import 23 | 24 | /*! 25 | @protocol MTAgentConnectionDelegate 26 | @abstract Defines an interface for delegates of MTAgentConnection to be notified if 27 | the connection to the agent failed. 28 | */ 29 | @protocol MTAgentConnectionDelegate 30 | 31 | /*! 32 | @method connection:didFailWithError: 33 | @abstract Called if the connection to the agent failed. 34 | @param connection A reference to the NSXPCConnection instance that failed. 35 | @param error A reference to a NSError object that indicates why the xpc connection failed. 36 | @discussion Delegates receive this message if the connection to the agent failed. 37 | */ 38 | - (void)connection:(NSXPCConnection*)connection didFailWithError:(NSError*)error; 39 | 40 | @end 41 | 42 | /*! 43 | @class MTAgentConnection 44 | @abstract A class that provides an easy way to connect to the Privileges agent. 45 | */ 46 | 47 | @interface MTAgentConnection : NSObject 48 | 49 | /*! 50 | @property delegate 51 | @abstract The receiver's connection delegate. 52 | @discussion The value of this property is an object conforming to the MTAgentConnectionDelegate protocol. 53 | */ 54 | @property (weak) id delegate; 55 | 56 | /*! 57 | @property connection 58 | @abstract A property to store the connection object. 59 | @discussion The value of this property is NSXPCConnection. 60 | */ 61 | @property (atomic, strong, readonly) NSXPCConnection *connection; 62 | 63 | /*! 64 | @property remoteObjectProxy 65 | @abstract A property to store the connection's remote object proxy. 66 | @discussion The value of this property is id. 67 | */ 68 | @property (atomic, strong, readonly) id remoteObjectProxy; 69 | 70 | /*! 71 | @method connectToXPCServiceWithRemoteObjectProxyReply: 72 | @abstract Returns a proxy for the xpc service. 73 | @param reply The reply block to call when the request is complete. 74 | @discussion Returns a proxy for the xpc service or nil if an error occurred. In case of an error 75 | the error object might contain information about the error that caused the operation 76 | to fail. 77 | */ 78 | - (void)connectToXPCServiceWithRemoteObjectProxyReply:(void (^)(id remoteObjectProxy, NSError *error))reply; 79 | 80 | /*! 81 | @method connectToAgentWithExportedObject:andExecuteCommandBlock: 82 | @abstract Connects to the agent and executes the given command block. 83 | @param exportedObject The object you want to export to the agent. May be nil. 84 | @param commandBlock The command block that should be executed after the connection has been established. 85 | */ 86 | - (void)connectToAgentWithExportedObject:(id)exportedObject 87 | andExecuteCommandBlock:(void(^)(void))commandBlock; 88 | 89 | /*! 90 | @method invalidate 91 | @abstract Invalidates the connection to the agent (and xpc service). 92 | */ 93 | - (void)invalidate; 94 | 95 | @end 96 | -------------------------------------------------------------------------------- /source/Shared/Classes/MTCodeSigning.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTCodeSigning.h 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | /*! 21 | @class MTCodeSigning 22 | @abstract A class that provides some methods related to code signing and sandboxing. 23 | */ 24 | 25 | @interface MTCodeSigning : NSObject 26 | 27 | /*! 28 | @method getSigningAuthorityWithError: 29 | @abstract Returns the current app's signing authority. 30 | @param error A reference to a NSError object that indicates why the xpc connection failed. 31 | @discussion Returns the current app's signing authority or nil if an error occurred. In case of an error 32 | the error object might contain information about the error that caused the operation 33 | to fail. 34 | */ 35 | + (NSString*)getSigningAuthorityWithError:(NSError**)error; 36 | 37 | /*! 38 | @method codeSigningRequirementsWithCommonName:bundleIdentifier:versionString: 39 | @abstract Returns the code signing requirements constructed from the given parameters. 40 | @param commonName The common name (signing authority) that should be used for the code signing requirements. 41 | @param bundleIdentifier The app's bundle identifier that should be used for the code signing requirements. 42 | @param versionString The app's version string (e.g. 2.0.0) that should be used for the code signing requirements. 43 | @discussion Returns a string containing the code signing requirements or nil if an error occurred. 44 | */ 45 | + (NSString*)codeSigningRequirementsWithCommonName:(NSString*)commonName 46 | bundleIdentifier:(NSString*)bundleIdentifier 47 | versionString:(NSString*)versionString; 48 | 49 | /*! 50 | @method sandboxStatusWithCompletionHandler: 51 | @abstract Returns whether the current application is sandboxed or not. 52 | @param completionHandler The completion handler to call when the request is complete. 53 | @discussion Returns YES if the current application is sandboxed, otherwise returns NO. In case of an error 54 | the error object might contain information about the error that caused the operation 55 | to fail. 56 | */ 57 | + (void)sandboxStatusWithCompletionHandler:(void (^)(BOOL isSandboxed, NSError *error))completionHandler; 58 | 59 | @end 60 | 61 | -------------------------------------------------------------------------------- /source/Shared/Classes/MTCodeSigning.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTCodeSigning.h 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTCodeSigning.h" 19 | 20 | @implementation MTCodeSigning 21 | 22 | + (NSString*)getSigningAuthorityWithError:(NSError**)error 23 | { 24 | OSStatus result = errSecSuccess; 25 | SecCodeRef helperCodeRef = NULL; 26 | NSString *returnValue = nil; 27 | NSString *errorMsg = nil; 28 | 29 | // get our code object 30 | result = SecCodeCopySelf(kSecCSDefaultFlags, &helperCodeRef); 31 | 32 | if (result != errSecSuccess) { 33 | 34 | errorMsg = [NSString stringWithFormat:@"Failed to copy code object: %d", result]; 35 | 36 | } else { 37 | 38 | // get our static code 39 | SecStaticCodeRef staticCodeRef = NULL; 40 | result = SecCodeCopyStaticCode(helperCodeRef, kSecCSDefaultFlags, &staticCodeRef); 41 | 42 | if (result != errSecSuccess) { 43 | 44 | errorMsg = [NSString stringWithFormat:@"Failed to get static code object: %d", result]; 45 | 46 | } else { 47 | 48 | // get our own signing information 49 | CFDictionaryRef signingInfo = NULL; 50 | result = SecCodeCopySigningInformation(staticCodeRef, kSecCSSigningInformation, &signingInfo); 51 | 52 | if (result != errSecSuccess) { 53 | 54 | errorMsg = [NSString stringWithFormat:@"Failed to get signing information: %d", result]; 55 | 56 | } else { 57 | 58 | CFArrayRef certChain = (CFArrayRef) CFDictionaryGetValue(signingInfo, kSecCodeInfoCertificates); 59 | 60 | if (certChain && CFGetTypeID(certChain) == CFArrayGetTypeID() && CFArrayGetCount(certChain) > 0) { 61 | 62 | SecCertificateRef issuerCert = (SecCertificateRef) CFArrayGetValueAtIndex(certChain, 0); 63 | 64 | if (issuerCert) { 65 | 66 | CFStringRef subjectCN = NULL; 67 | SecCertificateCopyCommonName(issuerCert, &subjectCN); 68 | if (subjectCN) { returnValue = CFBridgingRelease(subjectCN); } 69 | } 70 | } 71 | } 72 | 73 | if (signingInfo) { CFRelease(signingInfo); } 74 | } 75 | 76 | if (staticCodeRef) { CFRelease(staticCodeRef); } 77 | } 78 | 79 | if (helperCodeRef) { CFRelease(helperCodeRef); } 80 | 81 | if (errorMsg && error) { 82 | 83 | NSDictionary *errorDetail = [NSDictionary dictionaryWithObjectsAndKeys:errorMsg, NSLocalizedDescriptionKey, nil]; 84 | *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:100 userInfo:errorDetail]; 85 | } 86 | 87 | return returnValue; 88 | } 89 | 90 | + (NSString*)codeSigningRequirementsWithCommonName:(NSString*)commonName 91 | bundleIdentifier:(NSString*)bundleIdentifier 92 | versionString:(NSString*)versionString 93 | { 94 | NSString *reqString = [NSString stringWithFormat:@"anchor trusted and certificate leaf [subject.CN] = \"%@\" and info [CFBundleShortVersionString] >= \"%@\" and info [CFBundleIdentifier] = %@", commonName, versionString, bundleIdentifier]; 95 | 96 | return reqString; 97 | } 98 | 99 | + (void)sandboxStatusWithCompletionHandler:(void (^)(BOOL isSandboxed, NSError *error))completionHandler 100 | { 101 | if (completionHandler) { 102 | 103 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 104 | 105 | BOOL isSandboxed = NO; 106 | NSError *error = nil; 107 | 108 | SecCodeRef codeRef = NULL; 109 | CFDictionaryRef infoDict = NULL; 110 | CFTypeRef entitlements = NULL; 111 | 112 | OSStatus err = SecCodeCopySelf(kSecCSDefaultFlags, &codeRef); 113 | 114 | if (err == errSecSuccess) { 115 | 116 | err = SecCodeCopySigningInformation(codeRef, (SecCSFlags) kSecCSDynamicInformation, &infoDict); 117 | 118 | if (err == errSecSuccess) { 119 | 120 | if (CFDictionaryGetValueIfPresent(infoDict, kSecCodeInfoEntitlementsDict, &entitlements)) { 121 | 122 | if (entitlements != NULL && CFDictionaryGetValue(entitlements, CFSTR("com.apple.security.app-sandbox")) != NULL) { 123 | 124 | isSandboxed = YES; 125 | } 126 | 127 | } else { 128 | 129 | err = errSecMissingEntitlement; 130 | } 131 | } 132 | } 133 | 134 | if (err != errSecSuccess) { error = [NSError errorWithDomain:NSOSStatusErrorDomain code:err userInfo:nil]; } 135 | 136 | completionHandler(isSandboxed, error); 137 | }); 138 | } 139 | } 140 | 141 | @end 142 | -------------------------------------------------------------------------------- /source/Shared/Classes/MTIdentity.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTIdentity.h 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | #import 20 | #import 21 | #import 22 | 23 | /*! 24 | @class MTIdentity 25 | @abstract This class provides methods for handling user identities. 26 | */ 27 | 28 | @interface MTIdentity : NSObject 29 | 30 | /*! 31 | @method gidFromGroupName: 32 | @abstract Get the group id from a group name. 33 | @param groupName The short name of the group. 34 | @discussion Returns the id of the given group or -1 if an error occurred. 35 | */ 36 | + (int)gidFromGroupName:(NSString*)groupName; 37 | 38 | /*! 39 | @method groupMembershipForUser:groupID:error 40 | @abstract Check if a given user is member of a given group. 41 | @param userName The short name of the user. 42 | @param groupID The id of the group. 43 | @param error A reference to an NSError object that contains a detailed error message if an error occurred. May be nil. 44 | @discussion Returns YES if the user is member of the group, otherwise returns NO. 45 | */ 46 | + (BOOL)groupMembershipForUser:(NSString*)userName groupID:(gid_t)groupID error:(NSError**)error; 47 | 48 | /*! 49 | @method groupMembershipForUser:groupName:error 50 | @abstract Check if a given user is member of a given group. 51 | @param userName The short name of the user. 52 | @param groupName The name of the group. 53 | @param error A reference to an NSError object that contains a detailed error message if an error occurred. May be nil. 54 | @discussion Returns YES if the user is member of the group, otherwise returns NO. 55 | */ 56 | + (BOOL)groupMembershipForUser:(NSString*)userName groupName:(NSString*)groupName error:(NSError**)error; 57 | 58 | /*! 59 | @method authenticateUserWithReason:completionHandler 60 | @abstract Authenticate the user either by using Touch ID (if available) or password. 61 | @param authReason The reason for requesting authentication, which displays in the authentication dialog presented to the user. 62 | @param completionHandler The handler to call when the request is complete. 63 | @discussion Returns YES if authentication succeeded, otherwise returns NO. If an error occurred, the completion handler's NSError object 64 | contains error details. 65 | */ 66 | + (void)authenticateUserWithReason:(NSString*)authReason completionHandler:(void (^) (BOOL success, NSError *error))completionHandler; 67 | 68 | /*! 69 | @method authenticatePIVUserWithReason:completionHandler 70 | @abstract Authenticate the user either by using a smart card/PIV token or password. 71 | @param authReason The reason for requesting authentication, which displays in the authentication dialog presented to the user. 72 | @param completionHandler The handler to call when the request is complete. 73 | @discussion Returns YES if authentication succeeded, otherwise returns NO. If an error occurred, the completion handler's NSError object 74 | contains error details. 75 | */ 76 | + (void)authenticatePIVUserWithReason:(NSString*)authReason completionHandler:(void (^) (BOOL success, NSError *error))completionHandler; 77 | 78 | /*! 79 | @method verifyPassword:forUser 80 | @abstract Verifies if a given password can be used to authenticate a given user. 81 | @param userPassword The user's password. 82 | @param userName The short name of the user. 83 | @discussion Returns YES if verification succeeded, otherwise returns NO. 84 | */ 85 | + (BOOL)verifyPassword:(NSString*)userPassword forUser:(NSString*)userName; 86 | 87 | @end 88 | -------------------------------------------------------------------------------- /source/Shared/Classes/MTPrivilegesUser.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTPrivilegesUser.h 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | #import "MTIdentity.h" 20 | 21 | /*! 22 | @class MTPrivilegesUser 23 | @abstract This class provides methods for the current Privileges user to request and revoke administrator privileges. 24 | */ 25 | 26 | @interface MTPrivilegesUser : NSObject 27 | 28 | /*! 29 | @property userName 30 | @abstract Returns the user name of the MTPrivilegesUser. 31 | @discussion The value of this property is string. 32 | */ 33 | @property (nonatomic, strong, readonly) NSString *userName; 34 | 35 | /*! 36 | @method hasAdminPrivileges 37 | @abstract Get whether the MTPrivilegesUser has administrator privileges. 38 | @discussion Returns YES if the user has administrator privileges, otherwise returns NO. 39 | */ 40 | - (BOOL)hasAdminPrivileges; 41 | 42 | /*! 43 | @method hasUnexpectedPrivilegeState 44 | @abstract Get whether the privileges of the MTPrivilegesUser have an unexpected state. 45 | @discussion Returns YES if the privileges for the user have been changed by another process and therefore 46 | different from the privileges we have set for this user, otherwise returns NO. 47 | */ 48 | - (BOOL)hasUnexpectedPrivilegeState; 49 | 50 | /*! 51 | @method setUnexpectedPrivilegeState: 52 | @abstract Set whether the privileges for the MTPrivilegesUser are unexpected. 53 | @param unexpectedState A boolean indicating if the privileges are unexpected (YES) or not (NO). 54 | */ 55 | - (void)setUnexpectedPrivilegeState:(BOOL)unexpectedState; 56 | 57 | /*! 58 | @method requestAdminPrivilegesWithReason:completionHandler: 59 | @abstract Request administrator privileges for the current MTPrivilegesUser. 60 | @param reason A string containing the reason the user requests administrator privileges. May be nil. 61 | @param completionHandler The handler to call when the request is complete. 62 | @discussion Returns YES if the operation was successful, otherwise returns NO. 63 | */ 64 | - (void)requestAdminPrivilegesWithReason:(NSString*)reason completionHandler:(void(^)(BOOL success))completionHandler; 65 | 66 | /*! 67 | @method revokeAdminPrivilegesWithCompletionHandler: 68 | @abstract Revoke administrator privileges for the current MTPrivilegesUser. 69 | @param completionHandler The handler to call when the request is complete. 70 | @discussion Returns YES if the operation was successful, otherwise returns NO. 71 | */ 72 | - (void)revokeAdminPrivilegesWithCompletionHandler:(void(^)(BOOL success))completionHandler; 73 | 74 | /*! 75 | @method renewAdminPrivilegesWithCompletionHandler: 76 | @abstract Renew expiring administrator privileges for the current MTPrivilegesUser. 77 | @param completionHandler The handler to call when the request is complete. 78 | @discussion Returns YES if the operation was successful, otherwise returns NO. 79 | */ 80 | - (void)renewAdminPrivilegesWithCompletionHandler:(void(^)(BOOL success))completionHandler; 81 | 82 | /*! 83 | @method authenticateWithCompletionHandler: 84 | @abstract Authenticate the current MTPrivilegesUser. 85 | @param completionHandler The handler to call when the request is complete. 86 | @discussion Returns YES if the operation was successful, otherwise returns NO. 87 | */ 88 | - (void)authenticateWithCompletionHandler:(void(^)(BOOL success))completionHandler; 89 | 90 | /*! 91 | @method privilegesExpirationWithReply: 92 | @abstract Get the date when the current user's administrator privileges expire. 93 | @param reply The reply block to call when the request is complete. 94 | @discussion Returns the expiration date and the number of minutes remaining. Expiration date will be nil 95 | if the administrator privileges are already expired. 96 | */ 97 | - (void)privilegesExpirationWithReply:(void(^)(NSDate *expire, NSUInteger remaining))reply; 98 | 99 | /*! 100 | @method canExecuteFileAtURL:reply: 101 | @abstract Get whether the current user can execute the file at the given url. 102 | @param reply The reply block to call when the request is complete. 103 | @discussion Returns YES if the file can be executed by the current user, otherwise returns NO. 104 | */ 105 | - (void)canExecuteFileAtURL:(NSURL*)url reply:(void (^)(BOOL canExecute))reply; 106 | 107 | /*! 108 | @method useIsRestricted 109 | @abstract Get whether the app usage is restricted for the user. 110 | @discussion Returns YES if the app usage is restricted for the user, otherwise returns NO. 111 | */ 112 | - (BOOL)useIsRestricted; 113 | 114 | /*! 115 | @method isExcludedFromRevokeAtLogin 116 | @abstract Get whether the current user is excluded from the automatic privilege removal at login. 117 | @discussion Returns YES if the user is excluded, otherwise returns NO. 118 | */ 119 | - (BOOL)isExcludedFromRevokeAtLogin; 120 | 121 | @end 122 | 123 | -------------------------------------------------------------------------------- /source/Shared/Classes/MTSystemInfo.h: -------------------------------------------------------------------------------- 1 | /* 2 | MTSystemInfo.h 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import 19 | 20 | /*! 21 | @class MTSystemInfo 22 | @abstract This class provides methods to get some system information. 23 | */ 24 | 25 | @interface MTSystemInfo : NSObject 26 | 27 | /*! 28 | @method machineUUID 29 | @abstract Returns the uuid of the current machine. 30 | @discussion Returns a NSString containing the uuid or nil if an error occurred. 31 | */ 32 | + (NSString*)machineUUID; 33 | 34 | /*! 35 | @method sessionStartDate 36 | @abstract Returns the start date of the current login session. 37 | @discussion Returns the start date of the current login session or a date in the distant future if an error occurred. 38 | */ 39 | + (NSDate*)sessionStartDate; 40 | 41 | /*! 42 | @method isExecutableFileAtURL: 43 | @abstract Returns whether the file at the given url is executable. 44 | @param url The file url to check. 45 | @discussion Returns YES, if the file url is valid, the file exists and if it's executable. Otherwise returns NO. 46 | */ 47 | + (BOOL)isExecutableFileAtURL:(NSURL*)url; 48 | 49 | @end 50 | 51 | -------------------------------------------------------------------------------- /source/Shared/Classes/MTSystemInfo.m: -------------------------------------------------------------------------------- 1 | /* 2 | MTSystemInfo.m 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #import "MTSystemInfo.h" 19 | #import 20 | #import 21 | 22 | @implementation MTSystemInfo 23 | 24 | + (NSString*)machineUUID 25 | { 26 | NSString *returnValue = @""; 27 | 28 | // get the Platform Expert object 29 | io_service_t platformExpert = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice")); 30 | 31 | if (platformExpert) { 32 | 33 | CFStringRef uuid = IORegistryEntryCreateCFProperty(platformExpert, CFSTR(kIOPlatformUUIDKey), kCFAllocatorDefault, kNilOptions); 34 | 35 | if (uuid) { 36 | 37 | returnValue = (__bridge NSString *)(uuid); 38 | CFRelease(uuid); 39 | } 40 | 41 | IOObjectRelease(platformExpert); 42 | } 43 | 44 | return returnValue; 45 | } 46 | 47 | + (NSDate*)sessionStartDate 48 | { 49 | NSDate *startDate = [NSDate distantFuture]; 50 | 51 | size_t len = 4; 52 | int mib[len]; 53 | struct kinfo_proc kp; 54 | 55 | if (sysctlnametomib("kern.proc.pid", mib, &len) == 0) { 56 | 57 | // get the loginwindow process 58 | NSRunningApplication *app = [[NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.apple.loginwindow"] firstObject]; 59 | mib[3] = [app processIdentifier]; 60 | len = sizeof(kp); 61 | 62 | if (sysctl(mib, 4, &kp, &len, NULL, 0) == 0) { 63 | 64 | struct timeval processStartTime = kp.kp_proc.p_un.__p_starttime; 65 | startDate = [NSDate dateWithTimeIntervalSince1970:processStartTime.tv_sec + processStartTime.tv_usec / 1e6]; 66 | } 67 | } 68 | 69 | return startDate; 70 | } 71 | 72 | + (BOOL)isExecutableFileAtURL:(NSURL*)url 73 | { 74 | BOOL isExecutable = NO; 75 | 76 | if (url && [url isFileURL]) { 77 | 78 | NSDictionary *resourceValues = [url resourceValuesForKeys:[NSArray arrayWithObjects:NSURLIsPackageKey, NSURLIsExecutableKey, nil] 79 | error:nil 80 | ]; 81 | 82 | if (resourceValues && [[resourceValues objectForKey:NSURLIsPackageKey] boolValue]) { 83 | 84 | isExecutable = [[resourceValues objectForKey:NSURLIsExecutableKey] boolValue]; 85 | 86 | } else { 87 | 88 | int status = access([[url path] UTF8String], X_OK); 89 | isExecutable = (status == -1) ? NO : YES; 90 | } 91 | } 92 | 93 | return isExecutable; 94 | } 95 | 96 | @end 97 | -------------------------------------------------------------------------------- /source/Shared/Constants.h: -------------------------------------------------------------------------------- 1 | /* 2 | Constants.h 3 | Copyright 2016-2025 SAP SE 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | */ 17 | 18 | #define kMTAppName @"Privileges" 19 | #define kMTDaemonMachServiceName @"corp.sap.privileges.daemon.xpc" 20 | #define kMTAgentMachServiceName @"corp.sap.privileges.agent.xpc" 21 | #define kMTXPCServiceName @"corp.sap.privileges.xpcservice" 22 | #define kMTAppBundleIdentifier @"corp.sap.privileges" 23 | #define kMTAuthRightName "corp.sap.privileges.auth" 24 | #define kMTAppGroupIdentifier @"7R5ZEU67FQ.corp.sap.privileges" 25 | #define kMTDockTilePluginBundleIdentifier @"corp.sap.privileges.docktileplugin" 26 | #define kMTErrorDomain @"corp.sap.privileges.ErrorDomain" 27 | #define kMTWebhookEventTypeGranted @"corp.sap.privileges.granted" 28 | #define kMTWebhookEventTypeRevoked @"corp.sap.privileges.revoked" 29 | #define kMTGitHubURL @"https://github.com/SAP/macOS-enterprise-privileges" 30 | 31 | #define kMTAdminGroupID 80 32 | #define kMTExpirationDefault 20 33 | #define kMTReasonMinLengthDefault 10 34 | #define kMTReasonMaxLengthDefault 250 35 | #define kMTFixedExpirationIntervals @[@0, @5, @10, @20, @30, @60] 36 | #define kMTRevokeAtLoginThreshold 60 37 | 38 | #define kMTEnforcedPrivilegeTypeNone @"none" 39 | #define kMTEnforcedPrivilegeTypeAdmin @"admin" 40 | #define kMTEnforcedPrivilegeTypeUser @"user" 41 | 42 | #define kMTRemoteLoggingServerTypeSyslog @"syslog" 43 | #define kMTRemoteLoggingServerTypeWebhook @"webhook" 44 | 45 | // NSUserDefaults 46 | #define kMTDefaultsExpirationIntervalKey @"ExpirationInterval" 47 | #define kMTDefaultsAutoExpirationIntervalMaxKey @"ExpirationIntervalMax" 48 | #define kMTDefaultsEnforcePrivilegesKey @"EnforcePrivileges" 49 | #define kMTDefaultsAuthRequiredKey @"RequireAuthentication" 50 | #define kMTDefaultsAuthCLIBiometricsAllowedKey @"AllowCLIBiometricAuthentication" 51 | #define kMTDefaultsLimitToUserKey @"LimitToUser" 52 | #define kMTDefaultsLimitToGroupKey @"LimitToGroup" 53 | #define kMTDefaultsRequireReasonKey @"ReasonRequired" 54 | #define kMTDefaultsReasonMinLengthKey @"ReasonMinLength" 55 | #define kMTDefaultsReasonMaxLengthKey @"ReasonMaxLength" 56 | #define kMTDefaultsReasonPresetsKey @"ReasonPresetList" 57 | #define kMTDefaultsReasonCheckingEnabledKey @"ReasonCheckingEnabled" 58 | #define kMTDefaultsRemoteLoggingKey @"RemoteLogging" 59 | #define kMTDefaultsRemoteLoggingServerTypeKey @"ServerType" 60 | #define kMTDefaultsRemoteLoggingServerAddressKey @"ServerAddress" 61 | #define kMTDefaultsRemoteLoggingSyslogOptionsKey @"SyslogOptions" 62 | #define kMTDefaultsRemoteLoggingSyslogServerPortKey @"ServerPort" 63 | #define kMTDefaultsRemoteLoggingSyslogUseTLSKey @"UseTLS" 64 | #define kMTDefaultsRemoteLoggingSyslogFacilityKey @"LogFacility" 65 | #define kMTDefaultsRemoteLoggingSyslogSeverityKey @"LogSeverity" 66 | #define kMTDefaultsRemoteLoggingSyslogMaxSizeKey @"MaximumMessageSize" 67 | #define kMTDefaultsRemoteLoggingSyslogFormatKey @"MessageFormat" 68 | #define kMTDefaultsRemoteLoggingSyslogSDKey @"StructuredData" 69 | #define kMTDefaultsRemoteLoggingWebhookDataKey @"WebhookCustomData" 70 | #define kMTDefaultsHideOtherWindowsKey @"HideOtherWindows" 71 | #define kMTDefaultsRevokeAtLoginKey @"RevokePrivilegesAtLogin" 72 | #define kMTDefaultsRevokeAtLoginExcludedUsersKey @"RevokeAtLoginExcludedUsers" 73 | #define kMTDefaultsPostChangeExecutablePathKey @"PostChangeExecutablePath" 74 | #define kMTDefaultsPostChangeActionOnGrantOnlyKey @"PostChangeActionOnGrantOnly" 75 | #define kMTDefaultsAgentTimerExpirationKey @"TimerExpires" 76 | #define kMTDefaultsUnhideOtherWindowsKey @"UnhideOtherWindows" 77 | #define kMTDefaultsHideSettingsButtonKey @"HideSettingsButton" 78 | #define kMTDefaultsHideSettingsFromDockMenuKey @"HideSettingsFromDockMenu" 79 | #define kMTDefaultsHideSettingsFromStatusItemKey @"HideSettingsFromStatusItem" 80 | #define kMTDefaultsAllowPrivilegeRenewalKey @"AllowPrivilegeRenewal" 81 | #define kMTDefaultsRenewalFollowsAuthSettingKey @"RenewalFollowsAuthSetting" 82 | #define kMTDefaultsHideHelpButtonKey @"HideHelpButton" 83 | #define kMTDefaultsHelpButtonCustomURLKey @"HelpButtonCustomURL" 84 | #define kMTDefaultsPassReasonToExecutableKey @"PassReasonToExecutable" 85 | #define kMTDefaultsShowInMenuBarKey @"ShowInMenuBar" 86 | #define kMTDefaultsSettingsSelectedTabKey @"SettingsSelectedTab" 87 | #define kMTDefaultsEnableSmartCardSupportKey @"EnableSmartCardSupport" 88 | #define kMTDefaultsRenewalCustomActionKey @"RenewalCustomAction" 89 | #define kMTDefaultsRenewalCustomActionPathKey @"ActionExecutablePath" 90 | #define kMTDefaultsRenewalCustomActionIntervalKey @"ActionNotificationInterval" 91 | #define kMTDefaultsUnexpectedPrivilegeStateKey @"UnexpectedPrivilegeState" 92 | 93 | // NSNotification 94 | #define kMTNotificationNamePrivilegesDidChange @"corp.sap.privileges.PrivilegesDidChange" 95 | #define kMTNotificationNameExpirationTimeLeft @"corp.sap.privileges.ExpirationTimeLeft" 96 | #define kMTNotificationNameConfigDidChange @"corp.sap.privileges.ConfigDidChange" 97 | #define kMTNotificationCategoryIdentifier @"corp.sap.privileges.action" 98 | #define kMTNotificationActionIdentifierRenew @"corp.sap.privileges.action.renew" 99 | #define kMTNotificationNameAdminGroupDidChange @"corp.sap.privileges.AdminGroupDidChange" 100 | 101 | // NSNotification user info keys 102 | #define kMTNotificationKeyTimeLeft @"TimeLeft" 103 | #define kMTNotificationKeyPreferencesChanged @"PreferenceKey" 104 | --------------------------------------------------------------------------------