]> git.saurik.com Git - apple/security.git/blob - SecurityTool/authz.c
Security-57740.51.3.tar.gz
[apple/security.git] / SecurityTool / authz.c
1 /*
2 * Copyright (c) 2003-2004,2006-2007,2009-2010,2012-2014 Apple 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_tool.h"
32
33 // AEWP?
34
35 static AuthorizationRef
36 read_auth_ref_from_stdin()
37 {
38 AuthorizationRef auth_ref = NULL;
39 AuthorizationExternalForm extform;
40 ssize_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
58 static int
59 write_auth_ref_to_stdout(AuthorizationRef auth_ref)
60 {
61 AuthorizationExternalForm extform;
62 ssize_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
79 static void
80 write_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
94 static CFDictionaryRef
95 read_dict_from_stdin()
96 {
97 ssize_t 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
130 static CFPropertyListRef
131 read_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
178 bail:
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
189 static Boolean
190 write_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;
227 bail:
228 if (NULL != xmlData)
229 CFRelease(xmlData);
230 if (NULL != fileURL)
231 CFRelease(fileURL);
232
233 return status;
234 }
235
236 static void merge_dictionaries(const void *key, const void *value, void *mergeDict)
237 {
238 CFDictionarySetValue(mergeDict, key, value);
239 }
240
241 int
242 authorizationdb(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;
480 bail:
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
507 int
508 authorize(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
669 int
670 execute_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 ssize_t 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