]> git.saurik.com Git - apple/security.git/blobdiff - SecurityTool/macOS/authz.c
Security-59306.11.20.tar.gz
[apple/security.git] / SecurityTool / macOS / authz.c
diff --git a/SecurityTool/macOS/authz.c b/SecurityTool/macOS/authz.c
new file mode 100644 (file)
index 0000000..00208dd
--- /dev/null
@@ -0,0 +1,742 @@
+/*
+ * 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);
+}
+