AuthorizationTrampoline.cpp [plain text]
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <Security/Authorization.h>
#include <Security/debugging.h>
#include <Security/logging.h>
#define EXECUTERIGHT "system.privilege.admin"
static void fail(OSStatus cause) __attribute__ ((noreturn));
int main(int argc, const char *argv[])
{
Syslog::open("authexec", LOG_AUTH);
if (!argv[0] || !argv[1] || !argv[2]) {
Syslog::alert("invalid argument vector");
exit(1);
}
const char *pathToTool = argv[1];
const char *mboxFdText = argv[2];
const char **restOfArguments = argv + 3;
debug("authtramp", "trampoline(%s,%s)", pathToTool, mboxFdText);
AuthorizationExternalForm extForm;
int fd;
if (sscanf(mboxFdText, "auth %d", &fd) != 1)
return errAuthorizationInternal;
if (lseek(fd, 0, SEEK_SET) ||
read(fd, &extForm, sizeof(extForm)) != sizeof(extForm)) {
close(fd);
return errAuthorizationInternal;
}
AuthorizationRef auth;
if (OSStatus error = AuthorizationCreateFromExternalForm(&extForm, &auth))
fail(error);
debug("authtramp", "authorization recovered");
AuthorizationItem right = { EXECUTERIGHT, 0, NULL, 0 };
AuthorizationRights inRights = { 1, &right };
AuthorizationRights *outRights;
if (OSStatus error = AuthorizationCopyRights(auth, &inRights, NULL ,
kAuthorizationFlagExtendRights | kAuthorizationFlagInteractionAllowed, &outRights))
fail(error);
if (outRights->count != 1 || strcmp(outRights->items[0].name, EXECUTERIGHT))
fail(errAuthorizationDenied);
AuthorizationFree(auth, kAuthorizationFlagDefaults);
setenv("__AUTHORIZATION", mboxFdText, true);
int notify = dup(1); fcntl(notify, F_SETFD, 1); dup2(0, 1);
*(--restOfArguments) = pathToTool;
debug("authtramp", "trampoline executes %s", pathToTool);
Syslog::notice("executing %s", pathToTool);
execv(pathToTool, (char *const *)restOfArguments);
debug("authexec", "exec(%s) failed (errno=%d)", pathToTool, errno);
OSStatus error = errAuthorizationToolExecuteFailure;
write(notify, &error, sizeof(error));
exit(1);
}
void fail(OSStatus cause)
{
write(1, &cause, sizeof(cause)); debug("authtramp", "trampoline aborting with status %ld", cause);
exit(1);
}