PrivilegedHelperTool: Add source

Note: Currently not in use
This commit is contained in:
Mykola Grymalyuk
2024-05-20 11:22:58 -06:00
parent f7bcb26b10
commit 3906b80a68
3 changed files with 219 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
CC=clang
OUTPUT=com.dortania.opencore-legacy-patcher.privileged-helper
all: clean release
release: main.m
$(CC) -framework Foundation -framework Security -arch x86_64 -arch arm64 -mmacosx-version-min=10.9 -o $(OUTPUT) main.m
debug: main.m
$(CC) -framework Foundation -framework Security -arch x86_64 -arch arm64 -mmacosx-version-min=10.9 -o $(OUTPUT) main.m -DDEBUG
clean:
/bin/rm -f $(OUTPUT)

View File

@@ -0,0 +1,54 @@
#!/bin/zsh --no-rcs
# ------------------------------------------------------
# Privileged Helper Tool Installer
# ------------------------------------------------------
# Moves to expected destination and sets SUID bit.
# ------------------------------------------------------
# Developed for internal testing, end users should be
# using the PKG installer when released.
# ------------------------------------------------------
# MARK: Variables
# ---------------------------
helperName="com.dortania.opencore-legacy-patcher.privileged-helper"
helperPath="/Library/PrivilegedHelperTools/$helperName"
# MARK: Functions
# ---------------------------
function _setSUIDBit() {
local binaryPath=$1
# Check if path is a directory
if [[ -d $binaryPath ]]; then
/bin/chmod -R +s $binaryPath
else
/bin/chmod +s $binaryPath
fi
}
function _copyHelper() {
local sourcePath=$1
local destinationPath=$2
# Check if destination path exists
if [[ -e $destinationPath ]]; then
# Check if destination path is a directory
if [[ -d $destinationPath ]]; then
/bin/rm -rf $destinationPath
else
/bin/rm -f $destinationPath
fi
fi
# Copy source to destination
/bin/cp -R $sourcePath $destinationPath
}
# MARK: Main
# ---------------------------
_copyHelper "./$helperName" $helperPath
_setSUIDBit $helperPath

View File

@@ -0,0 +1,152 @@
/*
------------------------------------------------
OpenCore Legacy Patcher Privileged Helper Tool
------------------------------------------------
Designed as an alternative to an XPC service,
this tool is used to run commands as root.
------------------------------------------------
Server and client must have the same signing
certificate in order to run commands.
------------------------------------------------
*/
#import <Foundation/Foundation.h>
#import <Security/Security.h>
#include <libproc.h>
#define UTILITY_VERSION "1.0.0"
#define VALID_CLIENT_TEAM_ID @"S74BDJXQMD"
#define OCLP_PHT_ERROR_MISSING_ARGUMENTS 160
#define OCLP_PHT_ERROR_SET_UID_MISSING 161
#define OCLP_PHT_ERROR_SET_UID_FAILED 162
#define OCLP_PHT_ERROR_SELF_PATH_MISSING 163
#define OCLP_PHT_ERROR_PARENT_PATH_MISSING 164
#define OCLP_PHT_ERROR_SIGNING_INFORMATION_MISSING 165
#define OCLP_PHT_ERROR_INVALID_TEAM_ID 166
#define OCLP_PHT_ERROR_INVALID_CERTIFICATES 167
#define OCLP_PHT_ERROR_COMMAND_MISSING 168
#define OCLP_PHT_ERROR_COMMAND_FAILED 169
#define OCLP_PHT_ERROR_CATCH_ALL 170
NSDictionary *getSigningInformationFromPath(NSString *path) {
SecStaticCodeRef codeRef;
OSStatus status = SecStaticCodeCreateWithPath((__bridge CFURLRef)[NSURL fileURLWithPath:path], kSecCSDefaultFlags, &codeRef);
if (status != errSecSuccess) {
return nil;
}
CFDictionaryRef codeDict = NULL;
status = SecCodeCopySigningInformation(codeRef, kSecCSSigningInformation, &codeDict);
if (status != errSecSuccess) {
return nil;
}
return (__bridge NSDictionary *)codeDict;
}
NSString *getParentProcessPath() {
char pathbuf[PROC_PIDPATHINFO_MAXSIZE];
if (proc_pidpath(getppid(), pathbuf, sizeof(pathbuf)) <= 0) {
return nil;
}
NSString *path = [NSString stringWithUTF8String:pathbuf];
return path;
}
NSString *getProcessPath() {
NSString *path = [[NSBundle mainBundle] executablePath];
return path;
}
BOOL isSBitSet(NSString *path) {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSDictionary *attributes = [fileManager attributesOfItemAtPath:path error:nil];
if (attributes == nil) {
return NO;
}
return (attributes.filePosixPermissions & S_ISUID) != 0;
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
// We simply return if no arguments are passed
if (argc < 2) {
return OCLP_PHT_ERROR_MISSING_ARGUMENTS;
}
if (argc == 2 && (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-v") == 0)) {
printf("%s\n", UTILITY_VERSION);
return 0;
}
// Verify whether we can run as root
NSString *processPath = getProcessPath();
if (processPath == nil) {
return OCLP_PHT_ERROR_SELF_PATH_MISSING;
}
if (!isSBitSet(processPath)) {
return OCLP_PHT_ERROR_SET_UID_MISSING;
}
setuid(0);
if (getuid() != 0) {
return OCLP_PHT_ERROR_SET_UID_FAILED;
}
NSString *parentProcessPath = getParentProcessPath();
if (parentProcessPath == nil) {
return OCLP_PHT_ERROR_PARENT_PATH_MISSING;
}
NSDictionary *processSigningInformation = getSigningInformationFromPath(processPath);
NSDictionary *parentProcessSigningInformation = getSigningInformationFromPath(parentProcessPath);
if (processSigningInformation == nil || parentProcessSigningInformation == nil) {
return OCLP_PHT_ERROR_SIGNING_INFORMATION_MISSING;
}
#ifdef DEBUG
// Skip Team ID check in debug mode
// DO NOT USE IN PRODUCTION
#else
// Check Team ID
if (![processSigningInformation[@"teamIdentifier"] isEqualToString:VALID_CLIENT_TEAM_ID] || ![parentProcessSigningInformation[@"teamIdentifier"] isEqualToString:VALID_CLIENT_TEAM_ID]) {
return OCLP_PHT_ERROR_INVALID_TEAM_ID;
}
// Check Certificates
if (![processSigningInformation[@"certificates"] isEqualToArray:parentProcessSigningInformation[@"certificates"]]) {
return OCLP_PHT_ERROR_INVALID_CERTIFICATES;
}
#endif
NSString *command = nil;
NSArray *arguments = @[];
if (argc == 2) {
command = [NSString stringWithUTF8String:argv[1]];
} else {
command = [NSString stringWithUTF8String:argv[1]];
for (int i = 2; i < argc; i++) {
arguments = [arguments arrayByAddingObject:[NSString stringWithUTF8String:argv[i]]];
}
}
// Verify command exists
if (![[NSFileManager defaultManager] fileExistsAtPath:command]) {
return OCLP_PHT_ERROR_COMMAND_MISSING;
}
NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:command];
[task setArguments:arguments];
[task launch];
[task waitUntilExit];
return [task terminationStatus];
}
return OCLP_PHT_ERROR_CATCH_ALL; // Should never reach here
}