1/* 2 * Copyright (c) 2003-2004 Apple Computer, Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 * 23 * authz.c 24 */ 25 26#include <getopt.h> 27#include <stdio.h> 28#include <Security/AuthorizationPriv.h> 29 30#include "authz.h" 31#include "security.h" 32 33// AEWP? 34 35AuthorizationRef 36read_auth_ref_from_stdin() 37{ 38 AuthorizationRef auth_ref = NULL; 39 AuthorizationExternalForm extform; 40 size_t bytes_read; 41 42 while (kAuthorizationExternalFormLength != (bytes_read = read(STDIN_FILENO, &extform, kAuthorizationExternalFormLength))) 43 { 44 if ((bytes_read == -1) && ((errno != EAGAIN) || (errno != EINTR))) 45 break; 46 } 47 if (bytes_read != kAuthorizationExternalFormLength) 48 fprintf(stderr, "ERR: Failed to read authref\n"); 49 else 50 if (AuthorizationCreateFromExternalForm(&extform, &auth_ref)) 51 fprintf(stderr, "ERR: Failed to internalize authref\n"); 52 53 close(0); 54 55 return auth_ref; 56} 57 58int 59write_auth_ref_to_stdout(AuthorizationRef auth_ref) 60{ 61 AuthorizationExternalForm extform; 62 size_t bytes_written; 63 64 if (AuthorizationMakeExternalForm(auth_ref, &extform)) 65 return -1; 66 67 while (kAuthorizationExternalFormLength != (bytes_written = write(STDOUT_FILENO, &extform, kAuthorizationExternalFormLength))) 68 { 69 if ((bytes_written == -1) && ((errno != EAGAIN) || (errno != EINTR))) 70 break; 71 } 72 73 if (bytes_written == kAuthorizationExternalFormLength) 74 return 0; 75 76 return -1; 77} 78 79void 80write_dict_to_stdout(CFDictionaryRef dict) 81{ 82 if (!dict) 83 return; 84 85 CFDataRef right_definition_xml = CFPropertyListCreateXMLData(NULL, dict); 86 87 if (!right_definition_xml) 88 return; 89 90 write(STDOUT_FILENO, CFDataGetBytePtr(right_definition_xml), CFDataGetLength(right_definition_xml)); 91 CFRelease(right_definition_xml); 92} 93 94CFDictionaryRef 95read_dict_from_stdin() 96{ 97 int bytes_read = 0; 98 uint8_t buffer[4096]; 99 CFMutableDataRef data = CFDataCreateMutable(kCFAllocatorDefault, 0); 100 CFErrorRef err = NULL; 101 102 if (!data) 103 return NULL; 104 105 while (bytes_read = read(STDIN_FILENO, (void *)buffer, sizeof(buffer))) 106 { 107 if (bytes_read == -1) 108 break; 109 else 110 CFDataAppendBytes(data, buffer, bytes_read); 111 } 112 113 CFDictionaryRef right_dict = (CFDictionaryRef)CFPropertyListCreateWithData(kCFAllocatorDefault, data, kCFPropertyListImmutable, NULL, &err); 114 CFRelease(data); 115 116 if (NULL == right_dict) { 117 CFShow(err); 118 return NULL; 119 } 120 121 if (CFGetTypeID(right_dict) != CFDictionaryGetTypeID()) 122 { 123 fprintf(stderr, "This is not a dictionary.\n"); 124 CFRelease(right_dict); 125 return NULL; 126 } 127 return right_dict; 128} 129 130CFPropertyListRef 131read_plist_from_file(CFStringRef filePath) 132{ 133 CFTypeRef property = NULL; 134 CFPropertyListRef propertyList = NULL; 135 CFURLRef fileURL = NULL; 136 CFErrorRef errorString = NULL; 137 CFDataRef resourceData = NULL; 138 Boolean status = FALSE; 139 SInt32 errorCode = -1; 140 141 // Convert the path to a URL. 142 fileURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, filePath, kCFURLPOSIXPathStyle, false); 143 if (NULL == fileURL) { 144 goto bail; 145 } 146 property = CFURLCreatePropertyFromResource(kCFAllocatorDefault, fileURL, kCFURLFileExists, NULL); 147 if (NULL == property) { 148 goto bail; 149 } 150 status = CFBooleanGetValue(property); 151 if (!status) { 152 fprintf(stderr, "The file does not exist.\n"); 153 goto bail; 154 } 155 156 // Read the XML file. 157 status = CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault, fileURL, &resourceData, NULL, NULL, &errorCode); 158 if (!status) { 159 fprintf(stderr, "Error (%d) reading the file.\n", (int)errorCode); 160 goto bail; 161 } 162 163 // Reconstitute the dictionary using the XML data. 164 propertyList = CFPropertyListCreateWithData(kCFAllocatorDefault, resourceData, kCFPropertyListImmutable, NULL, &errorString); 165 if (NULL == propertyList) { 166 CFShow(errorString); 167 goto bail; 168 } 169 170 // Some error checking. 171 if (!CFPropertyListIsValid(propertyList, kCFPropertyListXMLFormat_v1_0) || CFGetTypeID(propertyList) != CFDictionaryGetTypeID()) { 172 fprintf(stderr, "The file is invalid.\n"); 173 CFRelease(propertyList); 174 propertyList = NULL; 175 goto bail; 176 } 177 178bail: 179 if (NULL != fileURL) 180 CFRelease(fileURL); 181 if (NULL != property) 182 CFRelease(property); 183 if (NULL != resourceData) 184 CFRelease(resourceData); 185 186 return propertyList; 187} 188 189Boolean 190write_plist_to_file(CFPropertyListRef propertyList, CFStringRef filePath) 191{ 192 CFTypeRef property = NULL; 193 CFURLRef fileURL = NULL; 194 CFDataRef xmlData = NULL; 195 Boolean status = FALSE; 196 SInt32 errorCode = -1; 197 CFErrorRef errorRef = NULL; 198 199 // Convert the path to a URL. 200 fileURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, filePath, kCFURLPOSIXPathStyle, false); 201 if (NULL == fileURL) { 202 goto bail; 203 } 204 property = CFURLCreatePropertyFromResource(kCFAllocatorDefault, fileURL, kCFURLFileExists, NULL); 205 if (NULL == property) { 206 goto bail; 207 } 208 if (!CFBooleanGetValue(property)) { 209 fprintf(stderr, "The file does not exist.\n"); 210 goto bail; 211 } 212 213 // Convert the property list into XML data. 214 xmlData = CFPropertyListCreateData(kCFAllocatorDefault, propertyList, kCFPropertyListXMLFormat_v1_0, 0, &errorRef); 215 if (errorRef) { 216 fprintf(stderr, "The file could not be written.\n"); 217 goto bail; 218 } 219 220 // Write the XML data to the file. 221 if (!CFURLWriteDataAndPropertiesToResource(fileURL, xmlData, NULL, &errorCode)) { 222 fprintf(stderr, "The file could not be written.\n"); 223 goto bail; 224 } 225 226 status = TRUE; 227bail: 228 if (NULL != xmlData) 229 CFRelease(xmlData); 230 if (NULL != fileURL) 231 CFRelease(fileURL); 232 233 return status; 234} 235 236static void merge_dictionaries(const void *key, const void *value, void *mergeDict) 237{ 238 CFDictionarySetValue(mergeDict, key, value); 239} 240 241int 242authorizationdb(int argc, char * const * argv) 243{ 244 AuthorizationRef auth_ref = NULL; 245 int ch; 246 while ((ch = getopt(argc, argv, "i")) != -1) 247 { 248 switch (ch) 249 { 250 case 'i': 251 auth_ref = read_auth_ref_from_stdin(); 252 break; 253 case '?': 254 default: 255 return 2; 256 } 257 } 258 259 argc -= optind; 260 argv += optind; 261 262 if (argc == 0) 263 return 2; // required right parameter(s) 264 265 OSStatus status; 266 267 if (argc > 1) 268 { 269 if (!auth_ref && AuthorizationCreate(NULL, NULL, 0, &auth_ref)) 270 return -1; 271 272 if (!strcmp("read", argv[0])) 273 { 274 CFDictionaryRef right_definition; 275 status = AuthorizationRightGet(argv[1], &right_definition); 276 if (!status) 277 { 278 write_dict_to_stdout(right_definition); 279 CFRelease(right_definition); 280 } 281 } 282 else if (!strcmp("write", argv[0])) 283 { 284 if (argc == 2) 285 { 286 CFDictionaryRef right_definition = read_dict_from_stdin(); 287 if (!right_definition) 288 return -1; 289 status = AuthorizationRightSet(auth_ref, argv[1], right_definition, NULL, NULL, NULL); 290 CFRelease(right_definition); 291 } 292 else if (argc == 3) 293 { 294 // argv[2] is shortcut string 295 CFStringRef shortcut_definition = CFStringCreateWithCStringNoCopy(NULL, argv[2], kCFStringEncodingUTF8, kCFAllocatorNull); 296 if (!shortcut_definition) 297 return -1; 298 status = AuthorizationRightSet(auth_ref, argv[1], shortcut_definition, NULL, NULL, NULL); 299 CFRelease(shortcut_definition); 300 } 301 else 302 return 2; // take one optional argument - no more 303 304 } 305 else if (!strcmp("remove", argv[0])) 306 { 307 status = AuthorizationRightRemove(auth_ref, argv[1]); 308 } 309 else if (!strcmp("smartcard", argv[0])) 310 { 311 if (argc == 2) 312 { 313 if(!strcmp("status", argv[1])) 314 { 315 const CFStringRef SMARTCARD_LINE = CFSTR("builtin:smartcard-sniffer,privileged"); 316 const CFStringRef MECHANISMS = CFSTR("mechanisms"); 317 const CFStringRef BUILTIN_LINE = CFSTR("builtin:policy-banner"); 318 const char* SYSTEM_LOGIN_CONSOLE = "system.login.console"; 319 const char* AUTHENTICATE = "authenticate"; 320 321 CFIndex requiredLine1 = -1; 322 CFIndex requiredLine2 = -1; 323 324 CFDictionaryRef right_definition; 325 status = AuthorizationRightGet(SYSTEM_LOGIN_CONSOLE, &right_definition); 326 if(!status) 327 { 328 CFArrayRef mechanisms; 329 330 Boolean res = CFDictionaryGetValueIfPresent(right_definition, MECHANISMS, (void*)&mechanisms); 331 if(res) 332 { 333 // now parse all array elements until "builtin:policy-banner" is found 334 CFIndex c = CFArrayGetCount(mechanisms); 335 CFStringRef mechanismName; 336 337 for (CFIndex i = 0; i < c; ++i) 338 { 339 mechanismName = CFArrayGetValueAtIndex(mechanisms, i); 340 if(CFStringCompare(mechanismName, BUILTIN_LINE, 0) == kCFCompareEqualTo) 341 { 342 if(i + 1 < c) 343 { 344 mechanismName = CFArrayGetValueAtIndex(mechanisms, i + 1); 345 if(CFStringCompare(mechanismName, SMARTCARD_LINE, 0) == kCFCompareEqualTo) 346 { 347 requiredLine1 = i + 1; 348 } 349 break; 350 } 351 } 352 } 353 } 354 CFRelease(right_definition); 355 } 356 status = AuthorizationRightGet(AUTHENTICATE, &right_definition); 357 if(!status) 358 { 359 CFArrayRef mechanisms; 360 361 Boolean res = CFDictionaryGetValueIfPresent(right_definition, MECHANISMS, (void*)&mechanisms); 362 if(res) 363 { 364 // now parse all array elements until "builtin:policy-banner" is found 365 CFIndex c = CFArrayGetCount(mechanisms); 366 CFStringRef mechanismName; 367 368 if(c > 0) 369 { 370 mechanismName = CFArrayGetValueAtIndex(mechanisms, 0); 371 if(CFStringCompare(mechanismName, SMARTCARD_LINE, 0) == kCFCompareEqualTo) 372 { 373 requiredLine2 = 0; 374 } 375 } 376 } 377 CFRelease(right_definition); 378 } 379 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"); 380 381 } 382 else if(!strcmp("disable", argv[1])) 383 status = AuthorizationEnableSmartCard(auth_ref, FALSE); 384 else if(!strcmp("enable", argv[1])) 385 status = AuthorizationEnableSmartCard(auth_ref, TRUE); 386 else 387 return 2; // unrecognized parameter 388 } 389 else 390 return 2; // required parameter missing 391 } 392 else if (!strcmp("merge", argv[0])) { 393 status = 1; 394 CFStringRef sourcePath = NULL; 395 CFStringRef destPath = NULL; 396 CFPropertyListRef sourcePlist = NULL; 397 CFPropertyListRef destPlist = NULL; 398 CFDictionaryRef sourceRights = NULL; 399 CFDictionaryRef sourceRules = NULL; 400 CFDictionaryRef destRights = NULL; 401 CFDictionaryRef destRules = NULL; 402 CFIndex rightsCount = 0; 403 CFIndex rulesCount = 0; 404 CFMutableDictionaryRef mergeRights = NULL; 405 CFMutableDictionaryRef mergeRules = NULL; 406 CFMutableDictionaryRef outDict = NULL; 407 408 if (argc < 2 || argc > 3) 409 return 2; 410 411 if (!strcmp("-", argv[1])) { 412 // Merging from <STDIN>. 413 sourcePlist = read_dict_from_stdin(); 414 } else { 415 sourcePath = CFStringCreateWithCString(kCFAllocatorDefault, argv[1], kCFStringEncodingUTF8); 416 if (NULL == sourcePath) { 417 goto bail; 418 } 419 sourcePlist = read_plist_from_file(sourcePath); 420 } 421 if (NULL == sourcePlist) 422 goto bail; 423 if (argc == 2) { 424 // Merging to /etc/authorization. 425 destPath = CFStringCreateWithCString(kCFAllocatorDefault, "/etc/authorization", kCFStringEncodingUTF8); 426 } else { 427 destPath = CFStringCreateWithCString(kCFAllocatorDefault, argv[2], kCFStringEncodingUTF8); 428 } 429 if (NULL == destPath) { 430 goto bail; 431 } 432 destPlist = read_plist_from_file(destPath); 433 if (NULL == destPlist) 434 goto bail; 435 436 sourceRights = CFDictionaryGetValue(sourcePlist, CFSTR("rights")); 437 sourceRules = CFDictionaryGetValue(sourcePlist, CFSTR("rules")); 438 destRights = CFDictionaryGetValue(destPlist, CFSTR("rights")); 439 destRules = CFDictionaryGetValue(destPlist, CFSTR("rules")); 440 if (sourceRights) 441 rightsCount += CFDictionaryGetCount(sourceRights); 442 if (destRights) 443 rightsCount += CFDictionaryGetCount(destRights); 444 mergeRights = CFDictionaryCreateMutable(NULL, rightsCount, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 445 if (NULL == mergeRights) { 446 goto bail; 447 } 448 if (sourceRules) 449 rulesCount += CFDictionaryGetCount(sourceRules); 450 if (destRules) 451 rulesCount += CFDictionaryGetCount(destRules); 452 mergeRules = CFDictionaryCreateMutable(NULL, rulesCount, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 453 if (NULL == mergeRules) { 454 goto bail; 455 } 456 457 if (destRights) 458 CFDictionaryApplyFunction(destRights, merge_dictionaries, mergeRights); 459 if (destRules) 460 CFDictionaryApplyFunction(destRules, merge_dictionaries, mergeRules); 461 if (sourceRights) 462 CFDictionaryApplyFunction(sourceRights, merge_dictionaries, mergeRights); 463 if (sourceRules) 464 CFDictionaryApplyFunction(sourceRules, merge_dictionaries, mergeRules); 465 466 outDict = CFDictionaryCreateMutable(NULL, 3, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 467 if (NULL == outDict) { 468 goto bail; 469 } 470 if (CFDictionaryContainsKey(sourcePlist, CFSTR("comment"))) 471 CFDictionaryAddValue(outDict, CFSTR("comment"), CFDictionaryGetValue(sourcePlist, CFSTR("comment"))); 472 else if (CFDictionaryContainsKey(destPlist, CFSTR("comment"))) 473 CFDictionaryAddValue(outDict, CFSTR("comment"), CFDictionaryGetValue(destPlist, CFSTR("comment"))); 474 CFDictionaryAddValue(outDict, CFSTR("rights"), mergeRights); 475 CFDictionaryAddValue(outDict, CFSTR("rules"), mergeRules); 476 if (!write_plist_to_file(outDict, destPath)) 477 goto bail; 478 479 status = noErr; 480bail: 481 if (sourcePath) 482 CFRelease(sourcePath); 483 if (destPath) 484 CFRelease(destPath); 485 if (sourcePlist) 486 CFRelease(sourcePlist); 487 if (destPlist) 488 CFRelease(destPlist); 489 if (outDict) 490 CFRelease(outDict); 491 } 492 else 493 return 2; 494 } 495 else 496 return 2; 497 498 if (auth_ref) 499 AuthorizationFree(auth_ref, 0); 500 501 if (!do_quiet) 502 fprintf(stderr, "%s (%d)\n", status ? "NO" : "YES", (int)status); 503 504 return (status ? -1 : 0); 505} 506 507int 508authorize(int argc, char * const *argv) 509{ 510 int ch; 511 OSStatus status; 512 513 Boolean user_interaction_allowed = FALSE, extend_rights = TRUE; 514 Boolean partial_rights = FALSE, destroy_rights = FALSE; 515 Boolean pre_authorize = FALSE, internalize = FALSE, externalize = FALSE; 516 Boolean wait = FALSE, explicit_credentials = FALSE; 517 Boolean isolate_explicit_credentials = FALSE, least_privileged = FALSE; 518 char *login = NULL; 519 520 while ((ch = getopt(argc, argv, "ucC:EpdPieqwxl")) != -1) 521 { 522 switch (ch) 523 { 524 case 'u': 525 user_interaction_allowed = TRUE; 526 break; 527 case 'c': 528 explicit_credentials = TRUE; 529 break; 530 case 'C': 531 explicit_credentials = TRUE; 532 login = optarg; 533 break; 534 case 'e': 535 externalize = TRUE; 536 break; 537 case 'E': 538 extend_rights = FALSE; 539 break; 540 case 'p': 541 partial_rights = TRUE; 542 break; 543 case 'd': 544 destroy_rights = TRUE; 545 break; 546 case 'P': 547 pre_authorize = TRUE; 548 break; 549 case 'i': 550 internalize = TRUE; 551 break; 552 case 'w': 553 wait = TRUE; 554 externalize = TRUE; 555 break; 556 case 'x': 557 isolate_explicit_credentials = TRUE; 558 break; 559 case 'l': 560 least_privileged = TRUE; 561 break; 562 case '?': 563 default: 564 return 2; /* @@@ Return 2 triggers usage message. */ 565 } 566 } 567 568 argc -= optind; 569 argv += optind; 570 571 if (argc == 0) 572 return 2; // required right parameter(s) 573 574// set up AuthorizationFlags 575 AuthorizationFlags flags = kAuthorizationFlagDefaults | 576 (user_interaction_allowed ? kAuthorizationFlagInteractionAllowed : 0) | 577 (extend_rights ? kAuthorizationFlagExtendRights : 0) | 578 (partial_rights ? kAuthorizationFlagPartialRights : 0) | 579 (pre_authorize ? kAuthorizationFlagPreAuthorize : 0) | 580 (least_privileged ? kAuthorizationFlagLeastPrivileged : 0); 581 582// set up AuthorizationRightSet 583 AuthorizationItem rights[argc]; 584 memset(rights, '\0', argc * sizeof(AuthorizationItem)); 585 AuthorizationItemSet rightset = { argc, rights }; 586 while (argc > 0) 587 rights[--argc].name = *argv++; 588 589 AuthorizationRef auth_ref = NULL; 590 591// internalize AuthorizationRef 592 if (internalize) 593 { 594 auth_ref = read_auth_ref_from_stdin(); 595 if (!auth_ref) 596 return 1; 597 } 598 599 if (!auth_ref && AuthorizationCreate(NULL, NULL, 600 (least_privileged ? kAuthorizationFlagLeastPrivileged : 0), 601 &auth_ref)) 602 return -1; 603 604// prepare environment if needed 605 AuthorizationEnvironment *envp = NULL; 606 if (explicit_credentials) { 607 if (!login) 608 login = getlogin(); 609 char *pass = getpass("Password:"); 610 if (!(login && pass)) 611 return 1; 612 static AuthorizationItem authenv[] = { 613 { kAuthorizationEnvironmentUsername }, 614 { kAuthorizationEnvironmentPassword }, 615 { kAuthorizationEnvironmentShared } // optional (see below) 616 }; 617 static AuthorizationEnvironment env = { 0, authenv }; 618 authenv[0].valueLength = strlen(login); 619 authenv[0].value = login; 620 authenv[1].valueLength = strlen(pass); 621 authenv[1].value = pass; 622 if (isolate_explicit_credentials) 623 env.count = 2; // do not send kAuthorizationEnvironmentShared 624 else 625 env.count = 3; // do send kAuthorizationEnvironmentShared 626 envp = &env; 627 } 628 629// perform Authorization 630 AuthorizationRights *granted_rights = NULL; 631 status = AuthorizationCopyRights(auth_ref, &rightset, envp, flags, &granted_rights); 632 633// externalize AuthorizationRef 634 if (externalize) 635 write_auth_ref_to_stdout(auth_ref); 636 637 if (!do_quiet) 638 fprintf(stderr, "%s (%d) ", status ? "NO" : "YES", (int)status); 639 640 if (!do_quiet && !status && granted_rights) 641 { 642 uint32_t index; 643 fprintf(stderr, "{ %d: ", (int)granted_rights->count); 644 for (index = 0; index < granted_rights->count; index++) 645 { 646 fprintf(stderr, "\"%s\"%s %c ", granted_rights->items[index].name, 647 (kAuthorizationFlagCanNotPreAuthorize & granted_rights->items[index].flags) ? " (cannot-preauthorize)" : "", 648 (index+1 != granted_rights->count) ? ',' : '}'); 649 } 650 AuthorizationFreeItemSet(granted_rights); 651 } 652 653 if (!do_quiet) 654 fprintf(stderr, "\n"); 655 656// wait for client to pick up AuthorizationRef 657 if (externalize && wait) 658 while (-1 != write(STDOUT_FILENO, NULL, 0)) 659 usleep(100); 660 661// drop AuthorizationRef 662 if (auth_ref) 663 AuthorizationFree(auth_ref, destroy_rights ? kAuthorizationFlagDestroyRights : 0); 664 665 return (status ? -1 : 0); 666} 667 668 669int 670execute_with_privileges(int argc, char * const *argv) 671{ 672 AuthorizationRef auth_ref = NULL; 673 int ch; 674 while ((ch = getopt(argc, argv, "i")) != -1) 675 { 676 switch (ch) 677 { 678 case 'i': 679 auth_ref = read_auth_ref_from_stdin(); 680 break; 681 case '?': 682 default: 683 return 2; 684 } 685 } 686 687 argc -= optind; 688 argv += optind; 689 690 if (argc == 0) 691 return 2; // required tool parameter(s) 692 693 OSStatus status; 694 695 if (!auth_ref && AuthorizationCreate(NULL, NULL, 0, &auth_ref)) 696 return -1; 697 698 FILE *communications_pipe = NULL; 699 700 status = AuthorizationExecuteWithPrivileges(auth_ref,argv[0], 0, (argc > 1) ? &argv[1] : NULL, &communications_pipe); 701 702 if (!do_quiet) 703 fprintf(stderr, "%s (%d) ", status ? "NO" : "YES", (int)status); 704 705 if (!status) 706 { 707 int bytes_read = 0; 708 uint8_t buffer[4096]; 709 710 while (bytes_read = read(STDIN_FILENO, &buffer, sizeof(buffer))) 711 { 712 if ((bytes_read == -1) && ((errno != EAGAIN) || (errno != EINTR))) 713 break; 714 else 715 while ((-1 == write(fileno(communications_pipe), buffer, bytes_read)) && 716 ((errno == EAGAIN) || (errno == EINTR))) 717 usleep(100); 718 } 719 } 720 721 return (status ? -1 : 0); 722} 723 724