PrivilegedOperations.c [plain text]
#include "PrivilegedOperations.h"
#include "ConfigurationAuthority.h"
#include <CoreFoundation/CoreFoundation.h>
#include <SystemConfiguration/SystemConfiguration.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <AssertMacros.h>
#include <Security/Security.h>
Boolean gToolApproved = false;
static pid_t execTool(const char *args[])
{
pid_t child;
child = vfork();
if (child == 0)
{
execv(args[0], (char *const *)args);
printf("exec of %s failed; errno = %d\n", args[0], errno);
_exit(-1); }
else
return child;
}
OSStatus EnsureToolInstalled(void)
{
CFURLRef bundleURL;
pid_t toolPID;
int status;
OSStatus err = noErr;
const char *args[] = { kToolPath, "0", "V", NULL };
char toolSourcePath[PATH_MAX] = {};
char toolInstallerPath[PATH_MAX] = {};
if (gToolApproved)
return noErr;
toolPID = execTool(args);
if (toolPID > 0)
{
waitpid(toolPID, &status, 0);
if (WIFEXITED(status) && WEXITSTATUS(status) == PRIV_OP_TOOL_VERS)
return noErr;
}
bundleURL = CFBundleCopyBundleURL(CFBundleGetBundleWithIdentifier(CFSTR("com.apple.preference.bonjour")) );
if (bundleURL != NULL)
{
CFURLGetFileSystemRepresentation(bundleURL, false, (UInt8*) toolSourcePath, sizeof toolSourcePath);
if (strlcat(toolSourcePath, "/Contents/Resources/" kToolName, sizeof toolSourcePath ) >= sizeof toolSourcePath ) return(-1);
CFURLGetFileSystemRepresentation(bundleURL, false, (UInt8*) toolInstallerPath, sizeof toolInstallerPath);
if (strlcat(toolInstallerPath, "/Contents/Resources/" kToolInstaller, sizeof toolInstallerPath) >= sizeof toolInstallerPath) return(-1);
}
else
return coreFoundationUnknownErr;
{
AuthorizationItem aewpRight = { kAuthorizationRightExecute, strlen(toolInstallerPath), toolInstallerPath, 0 };
AuthorizationItemSet rights = { 1, &aewpRight };
AuthorizationRef authRef;
err = AuthorizationCreate(&rights, (AuthorizationEnvironment*) NULL,
kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights |
kAuthorizationFlagPreAuthorize, &authRef);
if (err == noErr)
{
char *installerargs[] = { toolSourcePath, NULL };
err = AuthorizationExecuteWithPrivileges(authRef, toolInstallerPath, 0, installerargs, (FILE**) NULL);
if (err == noErr) {
int pid = wait(&status);
if (pid > 0 && WIFEXITED(status)) {
err = WEXITSTATUS(status);
if (err == noErr) {
gToolApproved = true;
}
} else {
err = -1;
}
}
(void) AuthorizationFree(authRef, kAuthorizationFlagDefaults);
}
}
return err;
}
static OSStatus ExecWithCmdAndParam(const char *subCmd, CFDataRef paramData)
{
OSStatus err = noErr;
int commFD, dataLen;
u_int32_t len;
pid_t child;
char fileNum[16];
UInt8 *buff;
const char *args[] = { kToolPath, NULL, "A", NULL, NULL };
AuthorizationExternalForm authExt;
err = ExternalizeAuthority(&authExt);
require_noerr(err, AuthFailed);
dataLen = CFDataGetLength(paramData);
buff = (UInt8*) malloc(dataLen * sizeof(UInt8));
require_action(buff != NULL, AllocBuffFailed, err=memFullErr;);
{
CFRange all = { 0, dataLen };
CFDataGetBytes(paramData, all, buff);
}
commFD = fileno(tmpfile());
sprintf(fileNum, "%d", commFD);
args[1] = fileNum;
args[3] = subCmd;
len = 0; write(commFD, &len, sizeof len);
len = sizeof authExt; write(commFD, &len, sizeof len);
write(commFD, &authExt, len);
len = 0; write(commFD, &len, sizeof len);
len = dataLen; write(commFD, &len, sizeof len);
write(commFD, buff, len);
child = execTool(args);
if (child > 0) {
int status;
waitpid(child, &status, 0);
if (WIFEXITED(status))
err = WEXITSTATUS(status);
}
close(commFD);
free(buff);
AllocBuffFailed:
AuthFailed:
return err;
}
OSStatus
WriteBrowseDomain(CFDataRef domainArrayData)
{
if (!CurrentlyAuthorized())
return authFailErr;
return ExecWithCmdAndParam("Wb", domainArrayData);
}
OSStatus
WriteRegistrationDomain(CFDataRef domainArrayData)
{
if (!CurrentlyAuthorized())
return authFailErr;
return ExecWithCmdAndParam("Wd", domainArrayData);
}
OSStatus
WriteHostname(CFDataRef domainArrayData)
{
if (!CurrentlyAuthorized())
return authFailErr;
return ExecWithCmdAndParam("Wh", domainArrayData);
}
OSStatus
SetKeyForDomain(CFDataRef secretData)
{
if (!CurrentlyAuthorized())
return authFailErr;
return ExecWithCmdAndParam("Wk", secretData);
}