mirror of
https://git.openafs.org/openafs.git
synced 2025-01-18 15:00:12 +00:00
DARWIN: Convert prefpane backup ops to privhelper
Convert the prefpane logic to backup various config files to privhelper, so it can work with macOS 10.8+. Specifically, define the new privhelper task "backup". Define a new variant to TaskUtil's executePrivTask() called executePrivTaskBackup() to use the new task type, and convert the prefpane code to use it. Remove the backupFile() method, since it's now unused. The new "backup" task has an argument (filename), so we don't need to define separate tasks for each file we want to backup. But check the given filename against a short list of files we know we deal with, just to make sure we don't accidentally mess with some other system file, since we're running as root. Change-Id: I066d8e95a50a52f7509487f9228ba03dd027ea36 Reviewed-on: https://gerrit.openafs.org/15959 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
56915e96d8
commit
75da4edd3c
@ -387,7 +387,6 @@
|
||||
-(void) startup;
|
||||
-(void) scanIpForCell:(DBCellElement*) cellElement allIP:(NSString*)allIP;
|
||||
-(void) backupConfigurationFiles;
|
||||
-(void) backupFile:(NSString*)localAfsFilePath;
|
||||
-(void) saveConfigurationFiles:(BOOL) makeBackup;
|
||||
-(void) saveCacheConfigurationFiles:(BOOL) makeBackup;
|
||||
-(void) installConfigurationFile:(NSString*)srcConfFile destPath:(NSString*) destPath;
|
||||
|
@ -1197,10 +1197,14 @@
|
||||
// backup original file
|
||||
if(makeBackup) {
|
||||
//cacheinfo
|
||||
[self backupFile:@"/etc/cacheinfo"];
|
||||
[TaskUtil executePrivTaskBackup:@"/etc/cacheinfo"];
|
||||
|
||||
//afsd.options
|
||||
[self backupFile:useAfsdConfVersion?AFSD_NEW_PREFERENCE_FILE:AFSD_OLD_PREFERENCE_FILE];
|
||||
if (useAfsdConfVersion) {
|
||||
[TaskUtil executePrivTaskBackup:AFSD_NEW_PREFERENCE_FILE];
|
||||
} else {
|
||||
[TaskUtil executePrivTaskBackup:AFSD_OLD_PREFERENCE_FILE];
|
||||
}
|
||||
}
|
||||
|
||||
// install cacheinfo
|
||||
@ -1264,13 +1268,13 @@
|
||||
|
||||
@try{
|
||||
//This cell
|
||||
[self backupFile:@"/etc/ThisCell"];
|
||||
[TaskUtil executePrivTaskBackup:@"/etc/ThisCell"];
|
||||
|
||||
//CellServDB
|
||||
[self backupFile:@"/etc/CellServDB"];
|
||||
[TaskUtil executePrivTaskBackup:@"/etc/CellServDB"];
|
||||
|
||||
//TheseCell
|
||||
[self backupFile:@"/etc/TheseCells"];
|
||||
[TaskUtil executePrivTaskBackup:@"/etc/TheseCells"];
|
||||
|
||||
} @catch (NSException *e) {
|
||||
@throw e;
|
||||
@ -1278,39 +1282,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// -(void) backupFile:(NSString*)localAfsFilePath
|
||||
// -------------------------------------------------------------------------------
|
||||
-(void) backupFile:(NSString*)localAfsFilePath
|
||||
{
|
||||
NSString *srcString = nil;
|
||||
NSMutableString *filePath = [[NSMutableString alloc] initWithCapacity:256];
|
||||
OSStatus err = noErr;
|
||||
@try{
|
||||
[filePath setString: installationPath];
|
||||
[filePath appendString: localAfsFilePath];
|
||||
|
||||
//Check if the file at path exist
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
if(![fileManager fileExistsAtPath:[filePath stringByExpandingTildeInPath]]) return;
|
||||
|
||||
// store the source path
|
||||
srcString = [filePath stringByExpandingTildeInPath];
|
||||
[filePath appendString: @".afscommander_bk"];
|
||||
|
||||
// check for presence of bk file
|
||||
if(![[NSFileManager defaultManager] fileExistsAtPath:[filePath stringByExpandingTildeInPath]]){
|
||||
// backup the file
|
||||
err = [futil autorizedCopy:srcString
|
||||
toPath:[filePath stringByExpandingTildeInPath]];
|
||||
}
|
||||
} @catch (NSException *e) {
|
||||
@throw e;
|
||||
} @finally {
|
||||
if(filePath) [filePath release];
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
// checkAfsStatus
|
||||
// This is called at least once per 60s, so avoid logging normal case that afs _is_ mounted.
|
||||
|
@ -17,5 +17,7 @@
|
||||
+(NSString*) searchExecutablePath:(NSString*)unixCommand;
|
||||
+(NSString*) executeTaskSearchingPath:(NSString*)unixCommand args:(NSArray*)args;
|
||||
+(NSString*) executeTask:(NSString*) taskName arguments:(NSArray *)args;
|
||||
+(int) executePrivTask:(const char *)task filename:(char *)filename;
|
||||
+(int) executePrivTask:(const char *)task;
|
||||
+(int) executePrivTaskBackup:(NSString *)filename;
|
||||
@end
|
||||
|
@ -85,6 +85,8 @@
|
||||
*
|
||||
* @param[in] task The name of the task to perform (e.g. "startup_enable").
|
||||
* See privhelper.c:ProcessRequest for what tasks we define.
|
||||
* @param[in] filename Used for the "backup" task. Don't specify this with
|
||||
* executePrivTask; use executePrivTaskBackup instead.
|
||||
*
|
||||
* @returns Return status of the task
|
||||
* @retval 0 success
|
||||
@ -92,7 +94,7 @@
|
||||
* @retval nonzero The return value of system() of a failed command for the
|
||||
* task.
|
||||
*/
|
||||
+(int) executePrivTask:(const char *)task {
|
||||
+(int) executePrivTask:(const char *)task filename:(char *)filename {
|
||||
int status = -1;
|
||||
|
||||
OSErr autherr = [[AuthUtil shared] autorize];
|
||||
@ -135,6 +137,9 @@
|
||||
}
|
||||
xpc_dictionary_set_string(msg, "task", task);
|
||||
xpc_dictionary_set_data(msg, "auth", &extForm, sizeof(extForm));
|
||||
if (filename != NULL) {
|
||||
xpc_dictionary_set_string(msg, "filename", filename);
|
||||
}
|
||||
|
||||
xpc_object_t reply = xpc_connection_send_message_with_reply_sync(conn, msg);
|
||||
if (reply == NULL) {
|
||||
@ -159,4 +164,12 @@
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
+(int) executePrivTask:(const char *)task {
|
||||
return [self executePrivTask:task filename:NULL];
|
||||
}
|
||||
|
||||
+(int) executePrivTaskBackup:(NSString *)filename {
|
||||
return [self executePrivTask:"backup" filename:[filename UTF8String]];
|
||||
}
|
||||
@end
|
||||
|
@ -48,6 +48,7 @@
|
||||
#define AFS_ID "org.openafs.filesystems.afs"
|
||||
#define AFS_PLIST "/Library/LaunchDaemons/org.openafs.filesystems.afs.plist"
|
||||
#define AFS_RC "/Library/OpenAFS/Tools/root.client/usr/vice/etc/afs.rc"
|
||||
#define CONFIG_PREFIX "/var/db/openafs"
|
||||
|
||||
/*
|
||||
* This is the code signing requirement imposed on anyone that connects to our
|
||||
@ -204,6 +205,94 @@ RunCommand(int log_failure, const char *arg1, const char *arg2,
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* To make extra sure we don't accidentally write to some other file on the
|
||||
* system, check any filename we're given against a specific list of files. If
|
||||
* the filename we're given isn't one of these, refuse to do anything.
|
||||
*/
|
||||
static int
|
||||
check_filename(const char *filename)
|
||||
{
|
||||
const char *allowlist[] = {
|
||||
"/etc/cacheinfo",
|
||||
"/etc/config/afs.conf",
|
||||
"/etc/config/afsd.options",
|
||||
"/etc/ThisCell",
|
||||
"/etc/CellServDB",
|
||||
"/etc/TheseCells",
|
||||
};
|
||||
int allowlist_len = sizeof(allowlist) / sizeof(allowlist[0]);
|
||||
int fname_i;
|
||||
|
||||
for (fname_i = 0; fname_i < allowlist_len; fname_i++) {
|
||||
if (strcmp(filename, allowlist[fname_i]) == 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Translate the given 'filename' (e.g., "/etc/ThisCell") into the full path to
|
||||
* the file on disk.
|
||||
*/
|
||||
static char *
|
||||
GetFullPath(const char *task, const char *filename)
|
||||
{
|
||||
int code;
|
||||
char *path;
|
||||
|
||||
code = check_filename(filename);
|
||||
if (code != 0) {
|
||||
syslog(LOG_WARNING, "%s: Task '%s' got invalid filename '%s'",
|
||||
PRIVHELPER_ID, task, filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
code = asprintf(&path, "%s%s", CONFIG_PREFIX, filename);
|
||||
if (code < 0) {
|
||||
mem_error();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copies "filename" to "filename.afscommander_bk".
|
||||
*/
|
||||
static int
|
||||
BackupFile(const char *filename)
|
||||
{
|
||||
int code;
|
||||
char *src_path = NULL;
|
||||
char *dest_path = NULL;
|
||||
|
||||
src_path = GetFullPath("backup", filename);
|
||||
if (src_path == NULL) {
|
||||
code = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
code = asprintf(&dest_path, "%s.afscommander_bk", src_path);
|
||||
if (code < 0) {
|
||||
dest_path = NULL;
|
||||
mem_error();
|
||||
goto done;
|
||||
}
|
||||
|
||||
code = RunCommand(1, "/bin/cp", src_path, dest_path, NULL);
|
||||
if (code != 0) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
free(src_path);
|
||||
free(dest_path);
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the requested privileged task.
|
||||
*
|
||||
@ -222,6 +311,9 @@ RunCommand(int log_failure, const char *arg1, const char *arg2,
|
||||
*
|
||||
* - afsd_stop: Run "afs.rc stop" to stop the OpenAFS client.
|
||||
*
|
||||
* - backup: Make a backup copy of the configuration file named in the argument
|
||||
* "filename". This copies file "X" to "X.afscommander_bk".
|
||||
*
|
||||
* @param[in] task The name of the requested task.
|
||||
* @param[in] event The XPC dictionary containing other task-specific
|
||||
* arguments.
|
||||
@ -249,6 +341,14 @@ ProcessRequest(const char *task, xpc_object_t event)
|
||||
|
||||
} else if (strcmp(task, "afsd_stop") == 0) {
|
||||
return RunCommand(1, AFS_RC, "stop", NULL, NULL);
|
||||
|
||||
} else if (strcmp(task, "backup") == 0) {
|
||||
const char *filename = xpc_dictionary_get_string(event, "filename");
|
||||
if (filename == NULL) {
|
||||
syslog(LOG_WARNING, "%s: Task backup missing filename", PRIVHELPER_ID);
|
||||
return -1;
|
||||
}
|
||||
return BackupFile(filename);
|
||||
}
|
||||
|
||||
syslog(LOG_WARNING, "%s: Received unknown task '%s'", PRIVHELPER_ID, task);
|
||||
|
Loading…
Reference in New Issue
Block a user