1 /* Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */
3 #include "Authorization.h"
4 #include "authd_private.h"
5 #include "authutilities.h"
8 #include <Security/AuthorizationPriv.h>
9 #include <Security/AuthorizationDB.h>
10 #include <Security/AuthorizationTags.h>
11 #include <Security/AuthorizationTagsPriv.h>
13 #include <xpc/private.h>
14 #include <mach/mach.h>
16 #include <AssertMacros.h>
17 #include <CoreFoundation/CFXPCBridge.h>
19 static dispatch_queue_t
20 get_authorization_dispatch_queue()
22 static dispatch_once_t onceToken
= 0;
23 static dispatch_queue_t connection_queue
= NULL
;
25 dispatch_once(&onceToken
, ^{
26 connection_queue
= dispatch_queue_create("authorization-connection-queue", DISPATCH_QUEUE_SERIAL
);
29 return connection_queue
;
32 static xpc_connection_t
33 get_authorization_connection()
35 static xpc_connection_t connection
= NULL
;
37 dispatch_sync(get_authorization_dispatch_queue(), ^{
38 if (connection
== NULL
) {
39 connection
= xpc_connection_create(SECURITY_AUTH_NAME
, NULL
);
42 syslog(LOG_ERR
, "Authorization, failed to create xpc connection to %s", SECURITY_AUTH_NAME
);
43 connection
= xpc_connection_create(SECURITY_AUTH_NAME
, NULL
);
46 xpc_connection_set_event_handler(connection
, ^(xpc_object_t event
) {
47 if (xpc_get_type(event
) == XPC_TYPE_ERROR
) {
48 if (event
== XPC_ERROR_CONNECTION_INVALID
) {
49 syslog(LOG_ERR
, "Authorization, server not available");
51 // XPC_ERROR_CONNECTION_INTERRUPTED
52 // XPC_ERROR_TERMINATION_IMMINENT
54 char * desc
= xpc_copy_description(event
);
55 syslog(LOG_ERR
, "Authorization, we should never get messages on this connection: %s", desc
);
60 xpc_connection_resume(connection
);
63 xpc_object_t message
= xpc_dictionary_create(NULL
, NULL
, 0);
64 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_SETUP
);
65 mach_port_t bootstrap
= MACH_PORT_NULL
;
66 task_get_bootstrap_port(mach_task_self(), &bootstrap
);
67 xpc_dictionary_set_mach_send(message
, AUTH_XPC_BOOTSTRAP
, bootstrap
);
68 xpc_object_t reply
= xpc_connection_send_message_with_reply_sync(connection
, message
);
69 xpc_release_safe(message
);
70 xpc_release_safe(reply
);
78 setItemSet(xpc_object_t message
, const char * key
, const AuthorizationItemSet
* itemSet
)
80 xpc_object_t serialized
= SerializeItemSet(itemSet
);
82 xpc_dictionary_set_value(message
, key
, serialized
);
83 xpc_release(serialized
);
87 OSStatus
AuthorizationCreate(const AuthorizationRights
*rights
,
88 const AuthorizationEnvironment
*environment
,
89 AuthorizationFlags flags
,
90 AuthorizationRef
*authorization
)
92 OSStatus status
= errAuthorizationInternal
;
93 xpc_object_t message
= NULL
;
94 xpc_object_t reply
= NULL
;
96 // require_action(!(rights == NULL && authorization == NULL), done, status = errAuthorizationInvalidSet);
99 message
= xpc_dictionary_create(NULL
, NULL
, 0);
100 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
102 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_CREATE
);
103 setItemSet(message
, AUTH_XPC_RIGHTS
, rights
);
104 setItemSet(message
, AUTH_XPC_ENVIRONMENT
, environment
);
105 xpc_dictionary_set_uint64(message
, AUTH_XPC_FLAGS
, flags
| (authorization
? 0 : kAuthorizationFlagNoData
));
108 reply
= xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message
);
109 require_action_quiet(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
110 require_action_quiet(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
113 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
116 if (authorization
&& status
== errAuthorizationSuccess
) {
118 const void * data
= xpc_dictionary_get_data(reply
, AUTH_XPC_BLOB
, &len
);
119 require_action(data
!= NULL
, done
, status
= errAuthorizationInternal
);
120 assert(len
== sizeof(AuthorizationBlob
));
122 AuthorizationBlob
* blob
= (AuthorizationBlob
*)calloc(1u, sizeof(AuthorizationBlob
));
123 require_action(blob
!= NULL
, done
, status
= errAuthorizationInternal
);
124 *blob
= *(AuthorizationBlob
*)data
;
126 *authorization
= (AuthorizationRef
)blob
;
130 xpc_release_safe(message
);
131 xpc_release_safe(reply
);
135 OSStatus
AuthorizationCreateWithAuditToken(audit_token_t token
,
136 const AuthorizationEnvironment
*environment
,
137 AuthorizationFlags flags
,
138 AuthorizationRef
*authorization
)
140 OSStatus status
= errAuthorizationInternal
;
141 xpc_object_t message
= NULL
;
142 xpc_object_t reply
= NULL
;
144 require_action(authorization
!= NULL
, done
, status
= errAuthorizationInvalidPointer
);
147 message
= xpc_dictionary_create(NULL
, NULL
, 0);
148 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
150 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_CREATE_WITH_AUDIT_TOKEN
);
151 xpc_dictionary_set_data(message
, AUTH_XPC_DATA
, &token
, sizeof(token
));
152 setItemSet(message
, AUTH_XPC_ENVIRONMENT
, environment
);
153 xpc_dictionary_set_uint64(message
, AUTH_XPC_FLAGS
, flags
);
156 reply
= xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message
);
157 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
158 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
161 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
164 if (status
== errAuthorizationSuccess
) {
166 const void * data
= xpc_dictionary_get_data(reply
, AUTH_XPC_BLOB
, &len
);
167 require_action(data
!= NULL
, done
, status
= errAuthorizationInternal
);
168 assert(len
== sizeof(AuthorizationBlob
));
170 AuthorizationBlob
* blob
= (AuthorizationBlob
*)calloc(1u, sizeof(AuthorizationBlob
));
171 require_action(blob
!= NULL
, done
, status
= errAuthorizationInternal
);
172 *blob
= *(AuthorizationBlob
*)data
;
174 *authorization
= (AuthorizationRef
)blob
;
178 xpc_release_safe(message
);
179 xpc_release_safe(reply
);
183 OSStatus
AuthorizationFree(AuthorizationRef authorization
, AuthorizationFlags flags
)
185 OSStatus status
= errAuthorizationInternal
;
186 xpc_object_t message
= NULL
;
187 xpc_object_t reply
= NULL
;
188 AuthorizationBlob
*blob
= NULL
;
190 require_action(authorization
!= NULL
, done
, status
= errAuthorizationInvalidRef
);
191 blob
= (AuthorizationBlob
*)authorization
;
194 message
= xpc_dictionary_create(NULL
, NULL
, 0);
195 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
197 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_FREE
);
198 xpc_dictionary_set_data(message
, AUTH_XPC_BLOB
, blob
, sizeof(AuthorizationBlob
));
199 xpc_dictionary_set_uint64(message
, AUTH_XPC_FLAGS
, flags
);
202 reply
= xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message
);
203 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
204 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
207 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
213 xpc_release_safe(message
);
214 xpc_release_safe(reply
);
219 _AuthorizationCopyRights_send_message(xpc_object_t message
, AuthorizationRights
**authorizedRights
)
221 OSStatus status
= errAuthorizationInternal
;
222 xpc_object_t reply
= NULL
;
225 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
228 reply
= xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message
);
229 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
230 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
233 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
236 if (authorizedRights
&& status
== errAuthorizationSuccess
) {
237 xpc_object_t tmpItems
= xpc_dictionary_get_value(reply
, AUTH_XPC_OUT_ITEMS
);
238 AuthorizationRights
* grantedRights
= DeserializeItemSet(tmpItems
);
239 require_action(grantedRights
!= NULL
, done
, status
= errAuthorizationInternal
);
241 *authorizedRights
= grantedRights
;
245 xpc_release_safe(reply
);
250 _AuthorizationCopyRights_prepare_message(AuthorizationRef authorization
, const AuthorizationRights
*rights
, const AuthorizationEnvironment
*environment
, AuthorizationFlags flags
, xpc_object_t
*message_out
)
252 OSStatus status
= errAuthorizationInternal
;
253 AuthorizationBlob
*blob
= NULL
;
254 xpc_object_t message
= xpc_dictionary_create(NULL
, NULL
, 0);
255 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
257 require_action(authorization
!= NULL
, done
, status
= errAuthorizationInvalidRef
);
258 blob
= (AuthorizationBlob
*)authorization
;
260 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_COPY_RIGHTS
);
261 xpc_dictionary_set_data(message
, AUTH_XPC_BLOB
, blob
, sizeof(AuthorizationBlob
));
262 setItemSet(message
, AUTH_XPC_RIGHTS
, rights
);
263 setItemSet(message
, AUTH_XPC_ENVIRONMENT
, environment
);
264 xpc_dictionary_set_uint64(message
, AUTH_XPC_FLAGS
, flags
);
266 *message_out
= message
;
268 status
= errAuthorizationSuccess
;
271 xpc_release_safe(message
);
275 OSStatus
AuthorizationCopyRights(AuthorizationRef authorization
,
276 const AuthorizationRights
*rights
,
277 const AuthorizationEnvironment
*environment
,
278 AuthorizationFlags flags
,
279 AuthorizationRights
**authorizedRights
)
281 OSStatus status
= errAuthorizationInternal
;
282 xpc_object_t message
= NULL
;
284 require_noerr(status
= _AuthorizationCopyRights_prepare_message(authorization
, rights
, environment
, flags
, &message
), done
);
285 require_noerr(status
= _AuthorizationCopyRights_send_message(message
, authorizedRights
), done
);
288 xpc_release_safe(message
);
293 void AuthorizationCopyRightsAsync(AuthorizationRef authorization
,
294 const AuthorizationRights
*rights
,
295 const AuthorizationEnvironment
*environment
,
296 AuthorizationFlags flags
,
297 AuthorizationAsyncCallback callbackBlock
)
299 OSStatus prepare_status
= errAuthorizationInternal
;
300 __block xpc_object_t message
= NULL
;
302 prepare_status
= _AuthorizationCopyRights_prepare_message(authorization
, rights
, environment
, flags
, &message
);
303 if (prepare_status
!= errAuthorizationSuccess
) {
304 callbackBlock(prepare_status
, NULL
);
307 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^{
308 AuthorizationRights
*blockAuthorizedRights
= NULL
;
309 OSStatus status
= _AuthorizationCopyRights_send_message(message
, &blockAuthorizedRights
);
310 callbackBlock(status
, blockAuthorizedRights
);
311 xpc_release_safe(message
);
315 OSStatus
AuthorizationDismiss()
317 OSStatus status
= errAuthorizationInternal
;
318 xpc_object_t message
= NULL
;
319 xpc_object_t reply
= NULL
;
322 message
= xpc_dictionary_create(NULL
, NULL
, 0);
323 require(message
!= NULL
, done
);
325 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_DISMISS
);
328 reply
= xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message
);
329 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
330 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
333 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
336 xpc_release_safe(message
);
337 xpc_release_safe(reply
);
341 OSStatus
AuthorizationCopyInfo(AuthorizationRef authorization
,
342 AuthorizationString tag
,
343 AuthorizationItemSet
**info
)
345 OSStatus status
= errAuthorizationInternal
;
346 xpc_object_t message
= NULL
;
347 xpc_object_t reply
= NULL
;
348 AuthorizationBlob
*blob
= NULL
;
350 require_action(info
!= NULL
, done
, status
= errAuthorizationInvalidSet
);
351 require_action(authorization
!= NULL
, done
, status
= errAuthorizationInvalidRef
);
352 blob
= (AuthorizationBlob
*)authorization
;
355 message
= xpc_dictionary_create(NULL
, NULL
, 0);
356 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
358 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_COPY_INFO
);
359 xpc_dictionary_set_data(message
, AUTH_XPC_BLOB
, blob
, sizeof(AuthorizationBlob
));
361 xpc_dictionary_set_string(message
, AUTH_XPC_TAG
, tag
);
365 reply
= xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message
);
366 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
367 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
370 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
373 if (info
&& status
== errAuthorizationSuccess
) {
374 xpc_object_t tmpItems
= xpc_dictionary_get_value(reply
, AUTH_XPC_OUT_ITEMS
);
375 AuthorizationRights
* outInfo
= DeserializeItemSet(tmpItems
);
376 require_action(outInfo
!= NULL
, done
, status
= errAuthorizationInternal
);
382 xpc_release_safe(message
);
383 xpc_release_safe(reply
);
387 OSStatus
AuthorizationMakeExternalForm(AuthorizationRef authorization
,
388 AuthorizationExternalForm
*extForm
)
390 OSStatus status
= errAuthorizationInternal
;
391 xpc_object_t message
= NULL
;
392 xpc_object_t reply
= NULL
;
393 AuthorizationBlob
*blob
= NULL
;
395 require_action(extForm
!= NULL
, done
, status
= errAuthorizationInvalidPointer
);
396 require_action(authorization
!= NULL
, done
, status
= errAuthorizationInvalidRef
);
397 blob
= (AuthorizationBlob
*)authorization
;
400 message
= xpc_dictionary_create(NULL
, NULL
, 0);
401 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
403 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_MAKE_EXTERNAL_FORM
);
404 xpc_dictionary_set_data(message
, AUTH_XPC_BLOB
, blob
, sizeof(AuthorizationBlob
));
407 reply
= xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message
);
408 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
409 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
412 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
415 if (status
== errAuthorizationSuccess
) {
417 const void * data
= xpc_dictionary_get_data(reply
, AUTH_XPC_EXTERNAL
, &len
);
418 require_action(data
!= NULL
, done
, status
= errAuthorizationInternal
);
419 assert(len
== sizeof(AuthorizationExternalForm
));
421 *extForm
= *(AuthorizationExternalForm
*)data
;
425 xpc_release_safe(message
);
426 xpc_release_safe(reply
);
430 OSStatus
AuthorizationCreateFromExternalForm(const AuthorizationExternalForm
*extForm
,
431 AuthorizationRef
*authorization
)
433 OSStatus status
= errAuthorizationInternal
;
434 xpc_object_t message
= NULL
;
435 xpc_object_t reply
= NULL
;
437 require_action(extForm
!= NULL
, done
, status
= errAuthorizationInvalidPointer
);
438 require_action(authorization
!= NULL
, done
, status
= errAuthorizationInvalidRef
);
441 message
= xpc_dictionary_create(NULL
, NULL
, 0);
442 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
444 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_CREATE_FROM_EXTERNAL_FORM
);
445 xpc_dictionary_set_data(message
, AUTH_XPC_EXTERNAL
, extForm
, sizeof(AuthorizationExternalForm
));
448 reply
= xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message
);
449 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
450 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
453 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
456 if (authorization
&& status
== errAuthorizationSuccess
) {
458 const void * data
= xpc_dictionary_get_data(reply
, AUTH_XPC_BLOB
, &len
);
459 require_action(data
!= NULL
, done
, status
= errAuthorizationInternal
);
460 assert(len
== sizeof(AuthorizationBlob
));
462 AuthorizationBlob
* blob
= (AuthorizationBlob
*)calloc(1u, sizeof(AuthorizationBlob
));
463 require_action(blob
!= NULL
, done
, status
= errAuthorizationInternal
);
464 *blob
= *(AuthorizationBlob
*)data
;
466 *authorization
= (AuthorizationRef
)blob
;
470 xpc_release_safe(message
);
471 xpc_release_safe(reply
);
475 OSStatus
AuthorizationFreeItemSet(AuthorizationItemSet
*set
)
478 return errAuthorizationSuccess
;
481 OSStatus
AuthorizationEnableSmartCard(AuthorizationRef authRef
, Boolean enable
)
483 OSStatus status
= errAuthorizationInternal
;
484 xpc_object_t message
= NULL
;
485 xpc_object_t reply
= NULL
;
486 AuthorizationBlob
*blob
= NULL
;
489 message
= xpc_dictionary_create(NULL
, NULL
, 0);
490 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
491 require_action(authRef
!= NULL
, done
, status
= errAuthorizationInvalidRef
);
492 blob
= (AuthorizationBlob
*)authRef
;
493 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_ENABLE_SMARTCARD
);
494 xpc_dictionary_set_data(message
, AUTH_XPC_BLOB
, blob
, sizeof(AuthorizationBlob
));
495 xpc_dictionary_set_bool(message
, AUTH_XPC_DATA
, enable
);
498 reply
= xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message
);
499 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
500 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
502 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
505 xpc_release_safe(message
);
506 xpc_release_safe(reply
);
511 OSStatus
AuthorizationRightGet(const char *rightName
,
512 CFDictionaryRef
*rightDefinition
)
514 OSStatus status
= errAuthorizationInternal
;
515 xpc_object_t message
= NULL
;
516 xpc_object_t reply
= NULL
;
518 require_action(rightName
!= NULL
, done
, status
= errAuthorizationInvalidPointer
);
521 message
= xpc_dictionary_create(NULL
, NULL
, 0);
522 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
524 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_RIGHT_GET
);
525 xpc_dictionary_set_string(message
, AUTH_XPC_RIGHT_NAME
, rightName
);
528 reply
= xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message
);
529 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
530 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
533 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
536 if (rightDefinition
&& status
== errAuthorizationSuccess
) {
537 xpc_object_t value
= xpc_dictionary_get_value(reply
, AUTH_XPC_DATA
);
538 require_action(value
!= NULL
, done
, status
= errAuthorizationInternal
);
539 require_action(xpc_get_type(value
) == XPC_TYPE_DICTIONARY
, done
, status
= errAuthorizationInternal
);
541 CFTypeRef cfdict
= _CFXPCCreateCFObjectFromXPCObject(value
);
542 require_action(cfdict
!= NULL
, done
, status
= errAuthorizationInternal
);
544 *rightDefinition
= cfdict
;
548 xpc_release_safe(message
);
549 xpc_release_safe(reply
);
553 OSStatus
AuthorizationRightSet(AuthorizationRef authRef
,
554 const char *rightName
,
555 CFTypeRef rightDefinition
,
556 CFStringRef descriptionKey
,
558 CFStringRef tableName
)
560 OSStatus status
= errAuthorizationInternal
;
561 xpc_object_t message
= NULL
;
562 xpc_object_t reply
= NULL
;
563 AuthorizationBlob
*blob
= NULL
;
564 CFMutableDictionaryRef rightDict
= NULL
;
565 CFBundleRef clientBundle
= bundle
;
571 require_action(rightDefinition
!= NULL
, done
, status
= errAuthorizationInvalidPointer
);
572 require_action(rightName
!= NULL
, done
, status
= errAuthorizationInvalidPointer
);
573 require_action(authRef
!= NULL
, done
, status
= errAuthorizationInvalidRef
);
574 blob
= (AuthorizationBlob
*)authRef
;
577 message
= xpc_dictionary_create(NULL
, NULL
, 0);
578 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
580 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_RIGHT_SET
);
581 xpc_dictionary_set_data(message
, AUTH_XPC_BLOB
, blob
, sizeof(AuthorizationBlob
));
582 xpc_dictionary_set_string(message
, AUTH_XPC_RIGHT_NAME
, rightName
);
585 if (CFGetTypeID(rightDefinition
) == CFStringGetTypeID()) {
586 rightDict
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
587 require_action(rightDict
!= NULL
, done
, status
= errAuthorizationInternal
);
589 CFDictionarySetValue(rightDict
, CFSTR(kAuthorizationRightRule
), rightDefinition
);
591 } else if (CFGetTypeID(rightDefinition
) == CFDictionaryGetTypeID()) {
592 rightDict
= CFDictionaryCreateMutableCopy(kCFAllocatorDefault
, 0, rightDefinition
);
593 require_action(rightDict
!= NULL
, done
, status
= errAuthorizationInternal
);
596 status
= errAuthorizationInvalidPointer
;
601 if (descriptionKey
) {
602 CFMutableDictionaryRef locDict
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
603 require_action(locDict
!= NULL
, done
, status
= errAuthorizationInternal
);
605 if (clientBundle
== NULL
) {
606 clientBundle
= CFBundleGetMainBundle();
607 CFRetain(clientBundle
);
611 CFArrayRef bundleLocalizations
= CFBundleCopyBundleLocalizations(clientBundle
);
612 if (bundleLocalizations
) {
613 // for every CFString in localizations do
614 CFIndex locIndex
, allLocs
= CFArrayGetCount(bundleLocalizations
);
615 for (locIndex
= 0; locIndex
< allLocs
; locIndex
++)
617 CFStringRef oneLocalization
= (CFStringRef
)CFArrayGetValueAtIndex(bundleLocalizations
, locIndex
);
619 if (!oneLocalization
)
622 // @@@ no way to get "Localized" and "strings" as constants?
623 CFURLRef locURL
= CFBundleCopyResourceURLForLocalization(clientBundle
, tableName
? tableName
: CFSTR("Localizable"), CFSTR("strings"), NULL
/*subDirName*/, oneLocalization
);
628 CFDataRef tableData
= NULL
;
630 CFStringRef errStr
= NULL
;
631 CFPropertyListRef stringTable
= NULL
;
633 CFURLCreateDataAndPropertiesFromResource(CFGetAllocator(clientBundle
), locURL
, &tableData
, NULL
, NULL
, &errCode
);
634 CFReleaseSafe(locURL
);
637 CFReleaseSafe(tableData
);
641 stringTable
= CFPropertyListCreateFromXMLData(CFGetAllocator(clientBundle
), tableData
, kCFPropertyListImmutable
, &errStr
);
642 CFReleaseSafe(errStr
);
643 CFReleaseSafe(tableData
);
645 CFStringRef value
= (CFStringRef
)CFDictionaryGetValue(stringTable
, descriptionKey
);
646 if (value
== NULL
|| CFEqual(value
, CFSTR(""))) {
647 CFReleaseSafe(stringTable
);
650 // oneLocalization/value into our dictionary
651 CFDictionarySetValue(locDict
, oneLocalization
, value
);
652 CFReleaseSafe(stringTable
);
655 CFReleaseSafe(bundleLocalizations
);
659 // add the description as the default localization into the dictionary
660 CFDictionarySetValue(locDict
, CFSTR(""), descriptionKey
);
662 // stuff localization table into right definition
663 CFDictionarySetValue(rightDict
, CFSTR(kAuthorizationRuleParameterDefaultPrompt
), locDict
);
664 CFReleaseSafe(locDict
);
667 xpc_object_t value
= _CFXPCCreateXPCObjectFromCFObject(rightDict
);
668 xpc_dictionary_set_value(message
, AUTH_XPC_DATA
, value
);
669 xpc_release_safe(value
);
672 reply
= xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message
);
673 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
674 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
677 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
680 CFReleaseSafe(clientBundle
);
681 CFReleaseSafe(rightDict
);
682 xpc_release_safe(message
);
683 xpc_release_safe(reply
);
687 OSStatus
AuthorizationRightRemove(AuthorizationRef authorization
,
688 const char *rightName
)
690 OSStatus status
= errAuthorizationInternal
;
691 xpc_object_t message
= NULL
;
692 xpc_object_t reply
= NULL
;
693 AuthorizationBlob
*blob
= NULL
;
695 require_action(rightName
!= NULL
, done
, status
= errAuthorizationInvalidPointer
);
696 require_action(authorization
!= NULL
, done
, status
= errAuthorizationInvalidRef
);
697 blob
= (AuthorizationBlob
*)authorization
;
700 message
= xpc_dictionary_create(NULL
, NULL
, 0);
701 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
703 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_RIGHT_REMOVE
);
704 xpc_dictionary_set_data(message
, AUTH_XPC_BLOB
, blob
, sizeof(AuthorizationBlob
));
705 xpc_dictionary_set_string(message
, AUTH_XPC_RIGHT_NAME
, rightName
);
708 reply
= xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message
);
709 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
710 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
713 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
716 xpc_release_safe(message
);
717 xpc_release_safe(reply
);