[AltServer] Fixes “SDK does not contain libarclite” error when archiving

This commit is contained in:
Riley Testut
2023-09-08 14:38:35 -05:00
parent 61f2347ece
commit 6af7651a25
12 changed files with 176 additions and 164 deletions

View File

@@ -1,30 +1,30 @@
/*
# STPrivilegedTask - NSTask-like wrapper around AuthorizationExecuteWithPrivileges
# Copyright (C) 2009-2017 Sveinbjorn Thordarson <sveinbjorn@sveinbjorn.org>
#
# BSD License
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of the copyright holder nor that of any other
# contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
STPrivilegedTask - NSTask-like wrapper around AuthorizationExecuteWithPrivileges
Copyright (C) 2008-2021 Sveinbjorn Thordarson <sveinbjorn@sveinbjorn.org>
BSD License
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor that of any other
contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "STPrivilegedTask.h"
@@ -37,8 +37,8 @@
// New error code denoting that AuthorizationExecuteWithPrivileges no longer exists
OSStatus const errAuthorizationFnNoLongerExists = -70001;
// Create fn pointer to AuthorizationExecuteWithPrivileges in case
// it doesn't exist in this version of MacOS
// Create fn pointer to AuthorizationExecuteWithPrivileges
// in case it doesn't exist in this version of macOS
static OSStatus (*_AuthExecuteWithPrivsFn)(AuthorizationRef authorization, const char *pathToTool, AuthorizationFlags options,
char * const *arguments, FILE **communicationsPipe) = NULL;
@@ -48,8 +48,7 @@ static OSStatus (*_AuthExecuteWithPrivsFn)(AuthorizationRef authorization, const
NSTimer *_checkStatusTimer;
}
+ (void)initialize;
{
+ (void)initialize {
// On 10.7, AuthorizationExecuteWithPrivileges is deprecated. We want
// to still use it since there's no good alternative (without requiring
// code signing). We'll look up the function through dyld and fail if
@@ -64,8 +63,7 @@ static OSStatus (*_AuthExecuteWithPrivsFn)(AuthorizationRef authorization, const
#pragma clang diagnostic pop
}
- (instancetype)init
{
- (instancetype)init {
self = [super init];
if (self) {
_launchPath = nil;
@@ -80,8 +78,7 @@ static OSStatus (*_AuthExecuteWithPrivsFn)(AuthorizationRef authorization, const
return self;
}
- (instancetype)initWithLaunchPath:(NSString *)path
{
- (instancetype)initWithLaunchPath:(NSString *)path {
self = [self init];
if (self) {
self.launchPath = path;
@@ -89,8 +86,8 @@ static OSStatus (*_AuthExecuteWithPrivsFn)(AuthorizationRef authorization, const
return self;
}
- (instancetype)initWithLaunchPath:(NSString *)path arguments:(NSArray *)args
{
- (instancetype)initWithLaunchPath:(NSString *)path
arguments:(NSArray *)args {
self = [self initWithLaunchPath:path];
if (self) {
self.arguments = args;
@@ -98,8 +95,9 @@ static OSStatus (*_AuthExecuteWithPrivsFn)(AuthorizationRef authorization, const
return self;
}
- (instancetype)initWithLaunchPath:(NSString *)path arguments:(NSArray *)args currentDirectory:(NSString *)cwd
{
- (instancetype)initWithLaunchPath:(NSString *)path
arguments:(NSArray *)args
currentDirectory:(NSString *)cwd {
self = [self initWithLaunchPath:path arguments:args];
if (self) {
self.currentDirectoryPath = cwd;
@@ -117,32 +115,33 @@ static OSStatus (*_AuthExecuteWithPrivsFn)(AuthorizationRef authorization, const
#pragma mark -
+ (STPrivilegedTask *)launchedPrivilegedTaskWithLaunchPath:(NSString *)path
{
+ (STPrivilegedTask *)launchedPrivilegedTaskWithLaunchPath:(NSString *)path {
STPrivilegedTask *task = [[STPrivilegedTask alloc] initWithLaunchPath:path];
[task launch];
[task waitUntilExit];
return task;
}
+ (STPrivilegedTask *)launchedPrivilegedTaskWithLaunchPath:(NSString *)path arguments:(NSArray *)args
{
+ (STPrivilegedTask *)launchedPrivilegedTaskWithLaunchPath:(NSString *)path arguments:(NSArray *)args {
STPrivilegedTask *task = [[STPrivilegedTask alloc] initWithLaunchPath:path arguments:args];
[task launch];
[task waitUntilExit];
return task;
}
+ (STPrivilegedTask *)launchedPrivilegedTaskWithLaunchPath:(NSString *)path arguments:(NSArray *)args currentDirectory:(NSString *)cwd
{
+ (STPrivilegedTask *)launchedPrivilegedTaskWithLaunchPath:(NSString *)path
arguments:(NSArray *)args
currentDirectory:(NSString *)cwd {
STPrivilegedTask *task = [[STPrivilegedTask alloc] initWithLaunchPath:path arguments:args currentDirectory:cwd];
[task launch];
[task waitUntilExit];
return task;
}
+ (STPrivilegedTask *)launchedPrivilegedTaskWithLaunchPath:(NSString *)path arguments:(NSArray *)args currentDirectory:(NSString *)cwd authorization:(AuthorizationRef)authorization
{
+ (STPrivilegedTask *)launchedPrivilegedTaskWithLaunchPath:(NSString *)path
arguments:(NSArray *)args
currentDirectory:(NSString *)cwd
authorization:(AuthorizationRef)authorization {
STPrivilegedTask *task = [[STPrivilegedTask alloc] initWithLaunchPath:path arguments:args currentDirectory:cwd];
[task launchWithAuthorization:authorization];
[task waitUntilExit];
@@ -152,8 +151,7 @@ static OSStatus (*_AuthExecuteWithPrivsFn)(AuthorizationRef authorization, const
# pragma mark -
// return 0 for success
- (OSStatus)launch
{
- (OSStatus)launch {
if (_isRunning) {
NSLog(@"Task already running: %@", [self description]);
return 0;
@@ -172,22 +170,19 @@ static OSStatus (*_AuthExecuteWithPrivsFn)(AuthorizationRef authorization, const
AuthorizationRights myRights = { 1, &myItems };
AuthorizationFlags flags = kAuthorizationFlagDefaults | kAuthorizationFlagInteractionAllowed | kAuthorizationFlagPreAuthorize | kAuthorizationFlagExtendRights;
// Use Apple's Authentication Manager APIs to get an Authorization Reference
// These Apple APIs are quite possibly the most horrible of the Mac OS X APIs
// create authorization reference
// Use Apple's Authentication Manager API to create an Authorization Reference
err = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authorizationRef);
if (err != errAuthorizationSuccess) {
return err;
}
// pre-authorize the privileged operation
// Pre-authorize the privileged operation
err = AuthorizationCopyRights(authorizationRef, &myRights, kAuthorizationEmptyEnvironment, flags, NULL);
if (err != errAuthorizationSuccess) {
return err;
}
// OK, at this point we have received authorization for the task.
// OK, at this point we have received authorization for the task so we launch it.
err = [self launchWithAuthorization:authorizationRef];
return err;
@@ -208,59 +203,60 @@ static OSStatus (*_AuthExecuteWithPrivsFn)(AuthorizationRef authorization, const
}
// Assuming the authorization is valid for the task.
// Let's prepare to launch it
// Let's prepare to launch it.
NSArray *arguments = self.arguments;
NSUInteger numberOfArguments = [arguments count];
char *args[numberOfArguments + 1];
NSUInteger numArgs = [arguments count];
char *args[numArgs + 1];
FILE *outputFile;
const char *toolPath = [self.launchPath fileSystemRepresentation];
// first, construct an array of c strings from NSArray w. arguments
for (int i = 0; i < numberOfArguments; i++) {
// First, construct an array of C strings w. all the arguments from NSArray
// This is the format required by AuthorizationExecuteWithPrivileges function
for (int i = 0; i < numArgs; i++) {
NSString *argString = arguments[i];
const char *fsrep = [argString fileSystemRepresentation];
NSUInteger stringLength = strlen(fsrep);
args[i] = malloc((stringLength + 1) * sizeof(char));
args[i] = calloc((stringLength + 1), sizeof(char));
snprintf(args[i], stringLength + 1, "%s", fsrep);
}
args[numberOfArguments] = NULL;
args[numArgs] = NULL;
// change to the current dir specified
// Change to the specified current working directory
// NB: This is process-wide and could interfere with the behaviour of concurrent tasks
char *prevCwd = (char *)getcwd(nil, 0);
chdir([self.currentDirectoryPath fileSystemRepresentation]);
//use Authorization Reference to execute script with privileges
// Use Authorization Reference to execute script with privileges.
// This is where the magic happens.
OSStatus err = _AuthExecuteWithPrivsFn(authorization, toolPath, kAuthorizationFlagDefaults, args, &outputFile);
// OK, now we're done executing, let's change back to old dir
chdir(prevCwd);
// free the malloc'd argument strings
for (int i = 0; i < numberOfArguments; i++) {
// Free the alloc'd argument strings
for (int i = 0; i < numArgs; i++) {
free(args[i]);
}
// we return err if execution failed
// We return err if execution failed
if (err != errAuthorizationSuccess) {
return err;
} else {
_isRunning = YES;
}
// get file handle for the command output
// Get file handle for the command output
_outputFileHandle = [[NSFileHandle alloc] initWithFileDescriptor:fileno(outputFile) closeOnDealloc:YES];
_processIdentifier = fcntl(fileno(outputFile), F_GETOWN, 0);
// start monitoring task
// Start monitoring task
_checkStatusTimer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(checkTaskStatus) userInfo:nil repeats:YES];
return err;
}
- (void)terminate
{
- (void)terminate {
// This doesn't work without a PID, and we can't get one. Stupid Security API.
// int ret = kill(pid, SIGKILL);
//
@@ -269,9 +265,8 @@ static OSStatus (*_AuthExecuteWithPrivsFn)(AuthorizationRef authorization, const
// }
}
// hang until task is done
- (void)waitUntilExit
{
// Hang until task is done
- (void)waitUntilExit {
if (!_isRunning) {
NSLog(@"Task %@ is not running", [super description]);
return;
@@ -282,15 +277,14 @@ static OSStatus (*_AuthExecuteWithPrivsFn)(AuthorizationRef authorization, const
int status;
pid_t pid = 0;
while ((pid = waitpid(_processIdentifier, &status, WNOHANG)) == 0) {
// do nothing
// Do nothing
}
_terminationStatus = WEXITSTATUS(status);
_isRunning = NO;
_terminationStatus = WEXITSTATUS(status);
}
// check if task has terminated
- (void)checkTaskStatus
{
// Check if task has terminated
- (void)checkTaskStatus {
int status;
pid_t pid = waitpid(_processIdentifier, &status, WNOHANG);
if (pid != 0) {
@@ -306,10 +300,9 @@ static OSStatus (*_AuthExecuteWithPrivsFn)(AuthorizationRef authorization, const
#pragma mark -
+ (BOOL)authorizationFunctionAvailable
{
+ (BOOL)authorizationFunctionAvailable {
if (!_AuthExecuteWithPrivsFn) {
// This version of OS X has finally removed this function. Return with an error.
// This version of macOS has finally removed this function.
return NO;
}
return YES;
@@ -317,9 +310,8 @@ static OSStatus (*_AuthExecuteWithPrivsFn)(AuthorizationRef authorization, const
#pragma mark -
// Nice description for debugging
- (NSString *)description
{
// Nice description for debugging purposes
- (NSString *)description {
NSString *commandDescription = [NSString stringWithString:self.launchPath];
for (NSString *arg in self.arguments) {