mirror of
https://git.openafs.org/openafs.git
synced 2025-01-18 15:00:12 +00:00
DARWIN: Convert prefpane startup ops to privhelper
Convert the logic for the "start at login" option in the prefpane to use privhelper, so it can work with macOS 10.8+. Specifically, define these new privhelper tasks: - startup_enable - startup_disable - startup_check And convert our startup-related logic in the prefpane to use them. Get rid of our now-unused method executeTaskWithAuth() and related methods. Change-Id: I2cb4c31f964529ab1af43ab7828c14eba7354af0 Reviewed-on: https://gerrit.openafs.org/15957 Tested-by: BuildBot <buildbot@rampaginggeek.com> Reviewed-by: Michael Meffie <mmeffie@sinenomine.net> Reviewed-by: Cheyenne Wills <cwills@sinenomine.net> Reviewed-by: Mark Vitale <mvitale@sinenomine.net> Reviewed-by: Andrew Deason <adeason@sinenomine.net>
This commit is contained in:
parent
120871f03f
commit
89eafda960
@ -750,14 +750,13 @@
|
||||
// afsStartupSwitchEvent:
|
||||
// -------------------------------------------------------------------------------
|
||||
- (IBAction) afsStartupSwitchEvent:(id) sender {
|
||||
NSString *rootHelperApp = [[self bundle] pathForResource:@"afshlp" ofType:@""];
|
||||
//get the new state
|
||||
startAFSAtLogin = [checkButtonAfsAtBootTime state];
|
||||
[PListManager launchctlStringCommandAuth:startAFSAtLogin?@"load":@"unload"
|
||||
option:[NSArray arrayWithObjects:@"-w", nil]
|
||||
plistName:@AFS_DAEMON_PATH
|
||||
helper:rootHelperApp
|
||||
withAuthRef:[[authView authorization] authorizationRef]];
|
||||
if (startAFSAtLogin) {
|
||||
[TaskUtil executePrivTask:"startup_enable"];
|
||||
} else {
|
||||
[TaskUtil executePrivTask:"startup_disable"];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -878,16 +877,13 @@
|
||||
{
|
||||
BOOL afsIsUp = [afsProperty checkAfsStatus];
|
||||
BOOL afsEnabledAtStartup = NO;
|
||||
NSString *rootHelperApp = [[self bundle] pathForResource:@"afshlp" ofType:@""];
|
||||
|
||||
if ([self isUnlocked]) {
|
||||
afsEnabledAtStartup = (
|
||||
[TaskUtil executeTaskWithAuth:@"/bin/launchctl"
|
||||
arguments:[NSArray arrayWithObjects:@"list",
|
||||
@"org.openafs.filesystems.afs", nil]
|
||||
helper:rootHelperApp
|
||||
withAuthRef:[[authView authorization] authorizationRef]
|
||||
] == noErr)?YES:NO;
|
||||
if ([TaskUtil executePrivTask:"startup_check"] == 0) {
|
||||
afsEnabledAtStartup = YES;
|
||||
} else {
|
||||
afsEnabledAtStartup = NO;
|
||||
}
|
||||
[checkButtonAfsAtBootTime setState:afsEnabledAtStartup];
|
||||
}
|
||||
|
||||
|
@ -75,12 +75,6 @@
|
||||
@discussion <#(comprehensive description)#>
|
||||
*/
|
||||
+(void) launchctlCommand:(BOOL)enable userDomain:(BOOL)userDomain option:(NSArray*)option plistName:(NSString*)plistName;
|
||||
/*!
|
||||
@method launchctlCommand
|
||||
@abstract exec the launchctl command on a particular plist job
|
||||
@discussion <#(comprehensive description)#>
|
||||
*/
|
||||
+(void) launchctlStringCommandAuth:(NSString*)operation option:(NSArray*)option plistName:(NSString*)plistName helper:(NSString *)helper withAuthRef:(AuthorizationRef)authRef;
|
||||
/*!
|
||||
@method launchdJobState
|
||||
@abstract check is a job has been submitted to launchd
|
||||
|
@ -314,31 +314,6 @@
|
||||
arguments:argument];
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// launchctlCommand:
|
||||
// -------------------------------------------------------------------------------
|
||||
+(void) launchctlStringCommandAuth:(NSString *)operation
|
||||
option:(NSArray *)option
|
||||
plistName:(NSString *)plistName
|
||||
helper:(NSString *)helper
|
||||
withAuthRef:(AuthorizationRef)authRef
|
||||
{
|
||||
NSMutableArray *argument = [NSMutableArray array];
|
||||
|
||||
//set the load unload
|
||||
[argument addObject:operation];
|
||||
|
||||
//if there are load the user custom option
|
||||
if(option) [argument addObjectsFromArray:option];
|
||||
|
||||
//construct the path
|
||||
[argument addObject: plistName];
|
||||
|
||||
//exec the command
|
||||
[TaskUtil executeTaskWithAuth:@"/bin/launchctl"
|
||||
arguments:argument helper:helper withAuthRef:authRef];
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// launchdJobState:
|
||||
// -------------------------------------------------------------------------------
|
||||
|
@ -17,7 +17,5 @@
|
||||
+(NSString*) searchExecutablePath:(NSString*)unixCommand;
|
||||
+(NSString*) executeTaskSearchingPath:(NSString*)unixCommand args:(NSArray*)args;
|
||||
+(NSString*) executeTask:(NSString*) taskName arguments:(NSArray *)args;
|
||||
+(int) executeTaskWithAuth:(NSString*) taskName arguments:(NSArray *)args authExtForm:(NSData*)auth;
|
||||
+(int) executeTaskWithAuth:(NSString*) taskName arguments:(NSArray *)args helper:(NSString *)helper withAuthRef:(AuthorizationRef)authRef;
|
||||
+(int) executePrivTask:(const char *)task;
|
||||
@end
|
||||
|
@ -75,81 +75,6 @@
|
||||
return [result autorelease];
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// executeTask:
|
||||
// -------------------------------------------------------------------------------
|
||||
+(int) executeTaskWithAuth:(NSString*) taskName arguments:(NSArray *)args helper:(NSString *)helper withAuthRef:(AuthorizationRef)authRef {
|
||||
const char *rootHelperApp = [helper fileSystemRepresentation];
|
||||
OSStatus status;
|
||||
AuthorizationFlags flags = kAuthorizationFlagDefaults;
|
||||
int count = [args count];
|
||||
char **myArguments = calloc(count + 2, sizeof(char *));
|
||||
int i=0;
|
||||
|
||||
myArguments[0] = strdup([taskName UTF8String]);
|
||||
for(i=0;i < count;i++) {
|
||||
const char *string = [[args objectAtIndex:i] UTF8String];
|
||||
if(!string)
|
||||
break;
|
||||
myArguments[1+i] = strdup(string);
|
||||
}
|
||||
myArguments[1+i] = NULL;
|
||||
|
||||
// should use SMJobBless but we need to sign things...
|
||||
status = AuthorizationExecuteWithPrivileges(authRef, rootHelperApp, flags, myArguments, NULL);
|
||||
|
||||
i = 0;
|
||||
while (myArguments[i] != NULL) {
|
||||
free(myArguments[i]);
|
||||
i++;
|
||||
}
|
||||
|
||||
free(myArguments);
|
||||
return status;
|
||||
}
|
||||
|
||||
+(int) executeTaskWithAuth:(NSString*) taskName arguments:(NSArray *)args authExtForm:(NSData*)auth {
|
||||
NSString *result = nil;
|
||||
int status = 0;
|
||||
NSFileHandle *file = nil;
|
||||
NSDictionary *environment = [NSDictionary dictionaryWithObjectsAndKeys: @"$PATH:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin",@"PATH",nil];
|
||||
|
||||
NSPipe *pipe = [NSPipe pipe];
|
||||
NSPipe *pipeIn = [NSPipe pipe];
|
||||
NSTask *taskToRun = [[NSTask alloc] init];
|
||||
|
||||
[taskToRun setLaunchPath: taskName];
|
||||
[taskToRun setArguments: args];
|
||||
[taskToRun setEnvironment:environment];
|
||||
[taskToRun setStandardOutput: pipe];
|
||||
[taskToRun setStandardInput: pipeIn];
|
||||
file = [pipe fileHandleForReading];
|
||||
//Write to standard in
|
||||
[taskToRun launch];
|
||||
|
||||
NSFileHandle* taskInput = [[ taskToRun standardInput ] fileHandleForWriting ];
|
||||
[taskInput writeData:auth];
|
||||
[taskToRun waitUntilExit];
|
||||
status = [taskToRun terminationStatus];
|
||||
if (status == 0){
|
||||
NSData *data = [file readDataToEndOfFile];
|
||||
// remove the \n character from unix command
|
||||
if([data length] > 0){
|
||||
NSData *realData = [NSData dataWithBytes:[data bytes]
|
||||
length:[data length]-1];
|
||||
|
||||
[taskToRun release];
|
||||
result = [[NSString alloc] initWithData: realData
|
||||
encoding: NSUTF8StringEncoding];
|
||||
[result release];
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a task that requires root access via privhelper.
|
||||
*
|
||||
|
@ -29,6 +29,9 @@
|
||||
#include <syslog.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <errno.h>
|
||||
#include <spawn.h>
|
||||
|
||||
#include <xpc/xpc.h>
|
||||
#include <Security/Security.h>
|
||||
@ -39,7 +42,11 @@
|
||||
|
||||
#include <xpc/xpc.h>
|
||||
|
||||
#define LAUNCHCTL "/bin/launchctl"
|
||||
|
||||
#define PRIVHELPER_ID "org.openafs.privhelper"
|
||||
#define AFS_ID "org.openafs.filesystems.afs"
|
||||
#define AFS_PLIST "/Library/LaunchDaemons/org.openafs.filesystems.afs.plist"
|
||||
|
||||
/*
|
||||
* This is the code signing requirement imposed on anyone that connects to our
|
||||
@ -157,10 +164,81 @@ SecCodeCreateWithXPCMessage(xpc_object_t event, SecCSFlags secflags, SecCodeRef
|
||||
}
|
||||
#endif /* !HAVE_SECCODECREATEWITHXPCMESSAGE */
|
||||
|
||||
static int
|
||||
RunCommand(int log_failure, const char *arg1, const char *arg2,
|
||||
const char *arg3, const char *arg4)
|
||||
{
|
||||
extern char **environ;
|
||||
pid_t pid;
|
||||
int code;
|
||||
int status;
|
||||
const char *argv[] = {
|
||||
arg1, arg2, arg3, arg4, NULL
|
||||
};
|
||||
|
||||
code = posix_spawn(&pid, argv[0], NULL, NULL, argv, environ);
|
||||
if (code != 0) {
|
||||
syslog(LOG_ERR, "%s: Failed to execute %s, error %d", PRIVHELPER_ID,
|
||||
argv[0], code);
|
||||
return -1;
|
||||
}
|
||||
|
||||
code = waitpid(pid, &status, 0);
|
||||
if (code <= 0) {
|
||||
syslog(LOG_ERR, "%s: waitpid for %s failed, error %d/%d",
|
||||
PRIVHELPER_ID, argv[0], code, errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
|
||||
/* Command exited successfully. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (log_failure) {
|
||||
syslog(LOG_WARNING, "%s: Command %s failed, status %d",
|
||||
PRIVHELPER_ID, argv[0], status);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the requested privileged task.
|
||||
*
|
||||
* We implement the following tasks:
|
||||
*
|
||||
* - startup_enable: Run "launchctl load" to configure the OpenAFS client to
|
||||
* run at startup.
|
||||
*
|
||||
* - startup_disable: Run "launchctl unload" to configure the OpenAFS client to
|
||||
* not run at startup.
|
||||
*
|
||||
* - startup_check: Run "launchctl list" to check whether OpenAFS is configured
|
||||
* to run at startup. If it is, return 0; otherwise, return nonzero.
|
||||
*
|
||||
* @param[in] task The name of the requested task.
|
||||
* @param[in] event The XPC dictionary containing other task-specific
|
||||
* arguments.
|
||||
*
|
||||
* @returns Return status of the task
|
||||
* @retval 0 success
|
||||
* @retval -1 internal error
|
||||
* @retval nonzero The return value of system() of a failed command for the
|
||||
* task.
|
||||
*/
|
||||
static int
|
||||
ProcessRequest(const char *task, xpc_object_t event)
|
||||
{
|
||||
/* Tasks we understand will be added here as they are implemented. */
|
||||
if (strcmp(task, "startup_enable") == 0) {
|
||||
return RunCommand(1, LAUNCHCTL, "load", "-w", AFS_PLIST);
|
||||
|
||||
} else if (strcmp(task, "startup_disable") == 0) {
|
||||
return RunCommand(1, LAUNCHCTL, "unload", "-w", AFS_PLIST);
|
||||
|
||||
} else if (strcmp(task, "startup_check") == 0) {
|
||||
return RunCommand(0, LAUNCHCTL, "list", AFS_ID, NULL);
|
||||
}
|
||||
|
||||
syslog(LOG_WARNING, "%s: Received unknown task '%s'", PRIVHELPER_ID, task);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user