--- /dev/null
+/*
+ * Copyright (c) 2003-2004,2006-2007,2009-2010,2012-2014 Apple Inc. All Rights Reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ *
+ * authz.c
+ */
+
+#include <getopt.h>
+#include <stdio.h>
+#include <Security/AuthorizationPriv.h>
+#include <utilities/SecCFRelease.h>
+
+#include "authz.h"
+#include "security_tool.h"
+
+// AEWP?
+
+static AuthorizationRef
+read_auth_ref_from_stdin()
+{
+ AuthorizationRef auth_ref = NULL;
+ AuthorizationExternalForm extform;
+ ssize_t bytes_read;
+
+ while (kAuthorizationExternalFormLength != (bytes_read = read(STDIN_FILENO, &extform, kAuthorizationExternalFormLength)))
+ {
+ if ((bytes_read == -1) && ((errno != EAGAIN) || (errno != EINTR)))
+ break;
+ }
+ if (bytes_read != kAuthorizationExternalFormLength)
+ fprintf(stderr, "ERR: Failed to read authref\n");
+ else
+ if (AuthorizationCreateFromExternalForm(&extform, &auth_ref))
+ fprintf(stderr, "ERR: Failed to internalize authref\n");
+
+ close(0);
+
+ return auth_ref;
+}
+
+static int
+write_auth_ref_to_stdout(AuthorizationRef auth_ref)
+{
+ AuthorizationExternalForm extform;
+ ssize_t bytes_written;
+
+ if (AuthorizationMakeExternalForm(auth_ref, &extform))
+ return -1;
+
+ while (kAuthorizationExternalFormLength != (bytes_written = write(STDOUT_FILENO, &extform, kAuthorizationExternalFormLength)))
+ {
+ if ((bytes_written == -1) && ((errno != EAGAIN) || (errno != EINTR)))
+ break;
+ }
+
+ if (bytes_written == kAuthorizationExternalFormLength)
+ return 0;
+
+ return -1;
+}
+
+static void
+write_dict_to_stdout(CFDictionaryRef dict)
+{
+ if (!dict)
+ return;
+
+ CFDataRef right_definition_xml = CFPropertyListCreateXMLData(NULL, dict);
+
+ if (!right_definition_xml)
+ return;
+
+ write(STDOUT_FILENO, CFDataGetBytePtr(right_definition_xml), CFDataGetLength(right_definition_xml));
+ CFRelease(right_definition_xml);
+}
+
+static CFDictionaryRef CF_RETURNS_RETAINED
+read_dict_from_stdin()
+{
+ ssize_t bytes_read = 0;
+ uint8_t buffer[4096];
+ CFMutableDataRef data = CFDataCreateMutable(kCFAllocatorDefault, 0);
+ CFErrorRef err = NULL;
+
+ if (!data)
+ return NULL;
+
+ while ((bytes_read = read(STDIN_FILENO, (void *)buffer, sizeof(buffer))))
+ {
+ if (bytes_read == -1)
+ break;
+ else
+ CFDataAppendBytes(data, buffer, bytes_read);
+ }
+
+ CFDictionaryRef right_dict = (CFDictionaryRef)CFPropertyListCreateWithData(kCFAllocatorDefault, data, kCFPropertyListImmutable, NULL, &err);
+ CFRelease(data);
+
+ if (NULL == right_dict) {
+ CFShow(err);
+ return NULL;
+ }
+
+ if (CFGetTypeID(right_dict) != CFDictionaryGetTypeID())
+ {
+ fprintf(stderr, "This is not a dictionary.\n");
+ CFRelease(right_dict);
+ return NULL;
+ }
+ return right_dict;
+}
+
+static CFPropertyListRef CF_RETURNS_RETAINED
+read_plist_from_file(CFStringRef filePath)
+{
+ CFTypeRef property = NULL;
+ CFPropertyListRef propertyList = NULL;
+ CFURLRef fileURL = NULL;
+ CFErrorRef errorString = NULL;
+ CFDataRef resourceData = NULL;
+ Boolean status = FALSE;
+ SInt32 errorCode = -1;
+
+ // Convert the path to a URL.
+ fileURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, filePath, kCFURLPOSIXPathStyle, false);
+ if (NULL == fileURL) {
+ goto bail;
+ }
+ property = CFURLCreatePropertyFromResource(kCFAllocatorDefault, fileURL, kCFURLFileExists, NULL);
+ if (NULL == property) {
+ goto bail;
+ }
+ status = CFBooleanGetValue(property);
+ if (!status) {
+ fprintf(stderr, "The file does not exist.\n");
+ goto bail;
+ }
+
+ // Read the XML file.
+ status = CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault, fileURL, &resourceData, NULL, NULL, &errorCode);
+ if (!status) {
+ fprintf(stderr, "Error (%d) reading the file.\n", (int)errorCode);
+ goto bail;
+ }
+
+ // Reconstitute the dictionary using the XML data.
+ propertyList = CFPropertyListCreateWithData(kCFAllocatorDefault, resourceData, kCFPropertyListImmutable, NULL, &errorString);
+ if (NULL == propertyList) {
+ CFShow(errorString);
+ goto bail;
+ }
+
+ // Some error checking.
+ if (!CFPropertyListIsValid(propertyList, kCFPropertyListXMLFormat_v1_0) || CFGetTypeID(propertyList) != CFDictionaryGetTypeID()) {
+ fprintf(stderr, "The file is invalid.\n");
+ CFRelease(propertyList);
+ propertyList = NULL;
+ goto bail;
+ }
+
+bail:
+ if (NULL != fileURL)
+ CFRelease(fileURL);
+ if (NULL != property)
+ CFRelease(property);
+ if (NULL != resourceData)
+ CFRelease(resourceData);
+
+ return propertyList;
+}
+
+static Boolean
+write_plist_to_file(CFPropertyListRef propertyList, CFStringRef filePath)
+{
+ CFTypeRef property = NULL;
+ CFURLRef fileURL = NULL;
+ CFDataRef xmlData = NULL;
+ Boolean status = FALSE;
+ SInt32 errorCode = -1;
+ CFErrorRef errorRef = NULL;
+
+ // Convert the path to a URL.
+ fileURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, filePath, kCFURLPOSIXPathStyle, false);
+ if (NULL == fileURL) {
+ goto bail;
+ }
+ property = CFURLCreatePropertyFromResource(kCFAllocatorDefault, fileURL, kCFURLFileExists, NULL);
+ if (NULL == property) {
+ goto bail;
+ }
+ if (!CFBooleanGetValue(property)) {
+ fprintf(stderr, "The file does not exist.\n");
+ goto bail;
+ }
+
+ // Convert the property list into XML data.
+ xmlData = CFPropertyListCreateData(kCFAllocatorDefault, propertyList, kCFPropertyListXMLFormat_v1_0, 0, &errorRef);
+ if (errorRef) {
+ fprintf(stderr, "The file could not be written.\n");
+ goto bail;
+ }
+
+ // Write the XML data to the file.
+ if (!CFURLWriteDataAndPropertiesToResource(fileURL, xmlData, NULL, &errorCode)) {
+ fprintf(stderr, "The file could not be written.\n");
+ goto bail;
+ }
+
+ status = TRUE;
+bail:
+ CFReleaseNull(property);
+ if (NULL != xmlData)
+ CFRelease(xmlData);
+ if (NULL != fileURL)
+ CFRelease(fileURL);
+
+ return status;
+}
+
+static void merge_dictionaries(const void *key, const void *value, void *mergeDict)
+{
+ CFDictionarySetValue(mergeDict, key, value);
+}
+
+int
+authorizationdb(int argc, char * const * argv)
+{
+ AuthorizationRef auth_ref = NULL;
+ int ch;
+ while ((ch = getopt(argc, argv, "i")) != -1)
+ {
+ switch (ch)
+ {
+ case 'i':
+ auth_ref = read_auth_ref_from_stdin();
+ break;
+ case '?':
+ default:
+ return SHOW_USAGE_MESSAGE;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc == 0)
+ return SHOW_USAGE_MESSAGE; // required right parameter(s)
+
+ OSStatus status;
+
+ if (argc > 1)
+ {
+ if (!auth_ref && AuthorizationCreate(NULL, NULL, 0, &auth_ref))
+ return -1;
+
+ if (!strcmp("read", argv[0]))
+ {
+ CFDictionaryRef right_definition;
+ status = AuthorizationRightGet(argv[1], &right_definition);
+ if (!status)
+ {
+ write_dict_to_stdout(right_definition);
+ CFRelease(right_definition);
+ }
+ }
+ else if (!strcmp("write", argv[0]))
+ {
+ if (argc == 2)
+ {
+ CFDictionaryRef right_definition = read_dict_from_stdin();
+ if (!right_definition)
+ return -1;
+ status = AuthorizationRightSet(auth_ref, argv[1], right_definition, NULL, NULL, NULL);
+ CFRelease(right_definition);
+ }
+ else if (argc == 3)
+ {
+ // argv[2] is shortcut string
+ CFStringRef shortcut_definition = CFStringCreateWithCStringNoCopy(NULL, argv[2], kCFStringEncodingUTF8, kCFAllocatorNull);
+ if (!shortcut_definition)
+ return -1;
+ status = AuthorizationRightSet(auth_ref, argv[1], shortcut_definition, NULL, NULL, NULL);
+ CFRelease(shortcut_definition);
+ }
+ else
+ return SHOW_USAGE_MESSAGE; // take one optional argument - no more
+
+ }
+ else if (!strcmp("remove", argv[0]))
+ {
+ status = AuthorizationRightRemove(auth_ref, argv[1]);
+ }
+ else if (!strcmp("smartcard", argv[0]))
+ {
+ if (argc == 2)
+ {
+ if(!strcmp("status", argv[1]))
+ {
+ const CFStringRef SMARTCARD_LINE = CFSTR("builtin:smartcard-sniffer,privileged");
+ const CFStringRef MECHANISMS = CFSTR("mechanisms");
+ const CFStringRef BUILTIN_LINE = CFSTR("builtin:policy-banner");
+ const char* SYSTEM_LOGIN_CONSOLE = "system.login.console";
+ const char* AUTHENTICATE = "authenticate";
+
+ CFIndex requiredLine1 = -1;
+ CFIndex requiredLine2 = -1;
+
+ CFDictionaryRef right_definition;
+ status = AuthorizationRightGet(SYSTEM_LOGIN_CONSOLE, &right_definition);
+ if(!status)
+ {
+ CFArrayRef mechanisms;
+
+ Boolean res = CFDictionaryGetValueIfPresent(right_definition, MECHANISMS, (void*)&mechanisms);
+ if(res)
+ {
+ // now parse all array elements until "builtin:policy-banner" is found
+ CFIndex c = CFArrayGetCount(mechanisms);
+ CFStringRef mechanismName;
+
+ for (CFIndex i = 0; i < c; ++i)
+ {
+ mechanismName = CFArrayGetValueAtIndex(mechanisms, i);
+ if(CFStringCompare(mechanismName, BUILTIN_LINE, 0) == kCFCompareEqualTo)
+ {
+ if(i + 1 < c)
+ {
+ mechanismName = CFArrayGetValueAtIndex(mechanisms, i + 1);
+ if(CFStringCompare(mechanismName, SMARTCARD_LINE, 0) == kCFCompareEqualTo)
+ {
+ requiredLine1 = i + 1;
+ }
+ break;
+ }
+ }
+ }
+ }
+ CFRelease(right_definition);
+ }
+ status = AuthorizationRightGet(AUTHENTICATE, &right_definition);
+ if(!status)
+ {
+ CFArrayRef mechanisms;
+
+ Boolean res = CFDictionaryGetValueIfPresent(right_definition, MECHANISMS, (void*)&mechanisms);
+ if(res)
+ {
+ // now parse all array elements until "builtin:policy-banner" is found
+ CFIndex c = CFArrayGetCount(mechanisms);
+ CFStringRef mechanismName;
+
+ if(c > 0)
+ {
+ mechanismName = CFArrayGetValueAtIndex(mechanisms, 0);
+ if(CFStringCompare(mechanismName, SMARTCARD_LINE, 0) == kCFCompareEqualTo)
+ {
+ requiredLine2 = 0;
+ }
+ }
+ }
+ CFRelease(right_definition);
+ }
+ printf("Current smartcard login state: %s (system.login.console %s, authentication rule %s)\n", requiredLine1 != -1 && requiredLine2 != -1 ?"enabled":"disabled", requiredLine1 != -1 ? "enabled":"disabled", requiredLine2 != -1 ? "enabled":"disabled");
+
+ }
+ else if(!strcmp("disable", argv[1]))
+ status = AuthorizationEnableSmartCard(auth_ref, FALSE);
+ else if(!strcmp("enable", argv[1]))
+ status = AuthorizationEnableSmartCard(auth_ref, TRUE);
+ else
+ return SHOW_USAGE_MESSAGE; // unrecognized parameter
+ }
+ else
+ return SHOW_USAGE_MESSAGE; // required parameter missing
+ }
+ else if (!strcmp("merge", argv[0])) {
+ status = 1;
+ CFStringRef sourcePath = NULL;
+ CFStringRef destPath = NULL;
+ CFPropertyListRef sourcePlist = NULL;
+ CFPropertyListRef destPlist = NULL;
+ CFDictionaryRef sourceRights = NULL;
+ CFDictionaryRef sourceRules = NULL;
+ CFDictionaryRef destRights = NULL;
+ CFDictionaryRef destRules = NULL;
+ CFIndex rightsCount = 0;
+ CFIndex rulesCount = 0;
+ CFMutableDictionaryRef mergeRights = NULL;
+ CFMutableDictionaryRef mergeRules = NULL;
+ CFMutableDictionaryRef outDict = NULL;
+
+ if (argc < 2 || argc > 3)
+ return SHOW_USAGE_MESSAGE;
+
+ if (!strcmp("-", argv[1])) {
+ // Merging from <STDIN>.
+ sourcePlist = read_dict_from_stdin();
+ } else {
+ sourcePath = CFStringCreateWithCString(kCFAllocatorDefault, argv[1], kCFStringEncodingUTF8);
+ if (NULL == sourcePath) {
+ goto bail;
+ }
+ sourcePlist = read_plist_from_file(sourcePath);
+ }
+ if (NULL == sourcePlist)
+ goto bail;
+ if (argc == 2) {
+ // Merging to /etc/authorization.
+ destPath = CFStringCreateWithCString(kCFAllocatorDefault, "/etc/authorization", kCFStringEncodingUTF8);
+ } else {
+ destPath = CFStringCreateWithCString(kCFAllocatorDefault, argv[2], kCFStringEncodingUTF8);
+ }
+ if (NULL == destPath) {
+ goto bail;
+ }
+ destPlist = read_plist_from_file(destPath);
+ if (NULL == destPlist)
+ goto bail;
+
+ sourceRights = CFDictionaryGetValue(sourcePlist, CFSTR("rights"));
+ sourceRules = CFDictionaryGetValue(sourcePlist, CFSTR("rules"));
+ destRights = CFDictionaryGetValue(destPlist, CFSTR("rights"));
+ destRules = CFDictionaryGetValue(destPlist, CFSTR("rules"));
+ if (sourceRights)
+ rightsCount += CFDictionaryGetCount(sourceRights);
+ if (destRights)
+ rightsCount += CFDictionaryGetCount(destRights);
+ mergeRights = CFDictionaryCreateMutable(NULL, rightsCount, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ if (NULL == mergeRights) {
+ goto bail;
+ }
+ if (sourceRules)
+ rulesCount += CFDictionaryGetCount(sourceRules);
+ if (destRules)
+ rulesCount += CFDictionaryGetCount(destRules);
+ mergeRules = CFDictionaryCreateMutable(NULL, rulesCount, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ if (NULL == mergeRules) {
+ goto bail;
+ }
+
+ if (destRights)
+ CFDictionaryApplyFunction(destRights, merge_dictionaries, mergeRights);
+ if (destRules)
+ CFDictionaryApplyFunction(destRules, merge_dictionaries, mergeRules);
+ if (sourceRights)
+ CFDictionaryApplyFunction(sourceRights, merge_dictionaries, mergeRights);
+ if (sourceRules)
+ CFDictionaryApplyFunction(sourceRules, merge_dictionaries, mergeRules);
+
+ outDict = CFDictionaryCreateMutable(NULL, 3, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ if (NULL == outDict) {
+ goto bail;
+ }
+ if (CFDictionaryContainsKey(sourcePlist, CFSTR("comment")))
+ CFDictionaryAddValue(outDict, CFSTR("comment"), CFDictionaryGetValue(sourcePlist, CFSTR("comment")));
+ else if (CFDictionaryContainsKey(destPlist, CFSTR("comment")))
+ CFDictionaryAddValue(outDict, CFSTR("comment"), CFDictionaryGetValue(destPlist, CFSTR("comment")));
+ CFDictionaryAddValue(outDict, CFSTR("rights"), mergeRights);
+ CFDictionaryAddValue(outDict, CFSTR("rules"), mergeRules);
+ if (!write_plist_to_file(outDict, destPath))
+ goto bail;
+
+ status = noErr;
+bail:
+ if (sourcePath)
+ CFRelease(sourcePath);
+ if (destPath)
+ CFRelease(destPath);
+ if (sourcePlist)
+ CFRelease(sourcePlist);
+ if (destPlist)
+ CFRelease(destPlist);
+ if (outDict)
+ CFRelease(outDict);
+ }
+ else
+ return SHOW_USAGE_MESSAGE;
+ }
+ else
+ return SHOW_USAGE_MESSAGE;
+
+ if (auth_ref)
+ AuthorizationFree(auth_ref, 0);
+
+ if (!do_quiet)
+ fprintf(stderr, "%s (%d)\n", status ? "NO" : "YES", (int)status);
+
+ return (status ? -1 : 0);
+}
+
+int
+authorize(int argc, char * const *argv)
+{
+ int ch;
+ int retval = 1;
+ OSStatus status;
+
+ Boolean user_interaction_allowed = FALSE, extend_rights = TRUE;
+ Boolean partial_rights = FALSE, destroy_rights = FALSE;
+ Boolean pre_authorize = FALSE, internalize = FALSE, externalize = FALSE;
+ Boolean wait = FALSE, explicit_credentials = FALSE;
+ Boolean isolate_explicit_credentials = FALSE, least_privileged = FALSE;
+ char *login = NULL;
+
+ while ((ch = getopt(argc, argv, "ucC:EpdPieqwxl")) != -1)
+ {
+ switch (ch)
+ {
+ case 'u':
+ user_interaction_allowed = TRUE;
+ break;
+ case 'c':
+ explicit_credentials = TRUE;
+ break;
+ case 'C':
+ explicit_credentials = TRUE;
+ login = optarg;
+ break;
+ case 'e':
+ externalize = TRUE;
+ break;
+ case 'E':
+ extend_rights = FALSE;
+ break;
+ case 'p':
+ partial_rights = TRUE;
+ break;
+ case 'd':
+ destroy_rights = TRUE;
+ break;
+ case 'P':
+ pre_authorize = TRUE;
+ break;
+ case 'i':
+ internalize = TRUE;
+ break;
+ case 'w':
+ wait = TRUE;
+ externalize = TRUE;
+ break;
+ case 'x':
+ isolate_explicit_credentials = TRUE;
+ break;
+ case 'l':
+ least_privileged = TRUE;
+ break;
+ case '?':
+ default:
+ return SHOW_USAGE_MESSAGE;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc == 0)
+ return SHOW_USAGE_MESSAGE; // required right parameter(s)
+
+// set up AuthorizationFlags
+ AuthorizationFlags flags = kAuthorizationFlagDefaults |
+ (user_interaction_allowed ? kAuthorizationFlagInteractionAllowed : 0) |
+ (extend_rights ? kAuthorizationFlagExtendRights : 0) |
+ (partial_rights ? kAuthorizationFlagPartialRights : 0) |
+ (pre_authorize ? kAuthorizationFlagPreAuthorize : 0) |
+ (least_privileged ? kAuthorizationFlagLeastPrivileged : 0);
+
+// set up AuthorizationRightSet
+ AuthorizationItem *rights = malloc(argc * sizeof(AuthorizationItem));
+ if (!rights) {
+ fprintf(stderr, "Out of memory\n");
+ retval = 1;
+ goto bail;
+ }
+ memset(rights, '\0', argc * sizeof(AuthorizationItem));
+ AuthorizationItemSet rightset = { argc, rights };
+ while (argc > 0)
+ rights[--argc].name = *argv++;
+
+ AuthorizationRef auth_ref = NULL;
+
+// internalize AuthorizationRef
+ if (internalize)
+ {
+ auth_ref = read_auth_ref_from_stdin();
+ if (!auth_ref) {
+ retval = 1;
+ goto bail;
+ }
+ }
+
+ if (!auth_ref && AuthorizationCreate(NULL, NULL,
+ (least_privileged ? kAuthorizationFlagLeastPrivileged : 0),
+ &auth_ref)) {
+ retval = -1;
+ goto bail;
+ }
+
+// prepare environment if needed
+ AuthorizationEnvironment *envp = NULL;
+ if (explicit_credentials) {
+ if (!login)
+ login = getlogin();
+ char *pass = getpass("Password:");
+ if (!(login && pass)) {
+ retval = 1;
+ goto bail;
+ }
+ static AuthorizationItem authenv[] = {
+ { kAuthorizationEnvironmentUsername },
+ { kAuthorizationEnvironmentPassword },
+ { kAuthorizationEnvironmentShared } // optional (see below)
+ };
+ static AuthorizationEnvironment env = { 0, authenv };
+ authenv[0].valueLength = strlen(login);
+ authenv[0].value = login;
+ authenv[1].valueLength = strlen(pass);
+ authenv[1].value = pass;
+ if (isolate_explicit_credentials)
+ env.count = 2; // do not send kAuthorizationEnvironmentShared
+ else
+ env.count = 3; // do send kAuthorizationEnvironmentShared
+ envp = &env;
+ }
+
+// perform Authorization
+ AuthorizationRights *granted_rights = NULL;
+ status = AuthorizationCopyRights(auth_ref, &rightset, envp, flags, &granted_rights);
+
+// externalize AuthorizationRef
+ if (externalize)
+ write_auth_ref_to_stdout(auth_ref);
+
+ if (!do_quiet)
+ fprintf(stderr, "%s (%d) ", status ? "NO" : "YES", (int)status);
+
+ if (!do_quiet && !status && granted_rights)
+ {
+ uint32_t index;
+ fprintf(stderr, "{ %d: ", (int)granted_rights->count);
+ for (index = 0; index < granted_rights->count; index++)
+ {
+ fprintf(stderr, "\"%s\"%s %c ", granted_rights->items[index].name,
+ (kAuthorizationFlagCanNotPreAuthorize & granted_rights->items[index].flags) ? " (cannot-preauthorize)" : "",
+ (index+1 != granted_rights->count) ? ',' : '}');
+ }
+ AuthorizationFreeItemSet(granted_rights);
+ }
+
+ if (!do_quiet)
+ fprintf(stderr, "\n");
+
+// wait for client to pick up AuthorizationRef
+ if (externalize && wait)
+ while (-1 != write(STDOUT_FILENO, NULL, 0))
+ usleep(100);
+
+// drop AuthorizationRef
+ if (auth_ref)
+ AuthorizationFree(auth_ref, destroy_rights ? kAuthorizationFlagDestroyRights : 0);
+
+ retval = (status ? -1 : 0);
+bail:
+ if (rights)
+ free(rights);
+
+ return retval;
+}
+
+
+int
+execute_with_privileges(int argc, char * const *argv)
+{
+ AuthorizationRef auth_ref = NULL;
+ int ch;
+ while ((ch = getopt(argc, argv, "i")) != -1)
+ {
+ switch (ch)
+ {
+ case 'i':
+ auth_ref = read_auth_ref_from_stdin();
+ break;
+ case '?':
+ default:
+ return SHOW_USAGE_MESSAGE;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc == 0)
+ return SHOW_USAGE_MESSAGE; // required tool parameter(s)
+
+ OSStatus status;
+
+ if (!auth_ref && AuthorizationCreate(NULL, NULL, 0, &auth_ref))
+ return -1;
+
+ FILE *communications_pipe = NULL;
+
+ status = AuthorizationExecuteWithPrivileges(auth_ref,argv[0], 0, (argc > 1) ? &argv[1] : NULL, &communications_pipe);
+
+ if (!do_quiet)
+ fprintf(stderr, "%s (%d) ", status ? "NO" : "YES", (int)status);
+
+ if (!status)
+ {
+ ssize_t bytes_read = 0;
+ uint8_t buffer[4096];
+
+ while ((bytes_read = read(STDIN_FILENO, &buffer, sizeof(buffer))))
+ {
+ if ((bytes_read == -1) && ((errno != EAGAIN) || (errno != EINTR)))
+ break;
+ else
+ while ((-1 == write(fileno(communications_pipe), buffer, bytes_read)) &&
+ ((errno == EAGAIN) || (errno == EINTR)))
+ usleep(100);
+ }
+ }
+
+ return (status ? -1 : 0);
+}
+