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 _AuthorizationPreauthorizeCredentials_send_message(xpc_object_t message
)
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 xpc_release_safe(reply
);
241 _AuthorizationPreauthorizeCredentials_prepare_message(AuthorizationRef authorization
, const AuthorizationItemSet
*credentials
, xpc_object_t
*message_out
)
243 OSStatus status
= errAuthorizationInternal
;
244 AuthorizationBlob
*blob
= NULL
;
245 xpc_object_t message
= xpc_dictionary_create(NULL
, NULL
, 0);
246 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
248 require_action(authorization
!= NULL
, done
, status
= errAuthorizationInvalidRef
);
249 blob
= (AuthorizationBlob
*)authorization
;
251 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_PREAUTHORIZE_CREDENTIALS
);
252 xpc_dictionary_set_data(message
, AUTH_XPC_BLOB
, blob
, sizeof(AuthorizationBlob
));
253 setItemSet(message
, AUTH_XPC_DATA
, credentials
);
255 *message_out
= message
;
257 status
= errAuthorizationSuccess
;
260 xpc_release_safe(message
);
264 OSStatus
AuthorizationPreauthorizeCredentials(AuthorizationRef authorization
, const AuthorizationItemSet
*credentials
)
266 OSStatus status
= errAuthorizationInternal
;
267 xpc_object_t message
= NULL
;
269 require_noerr(status
= _AuthorizationPreauthorizeCredentials_prepare_message(authorization
, credentials
, &message
), done
);
270 require_noerr(status
= _AuthorizationPreauthorizeCredentials_send_message(message
), done
);
273 xpc_release_safe(message
);
278 _AuthorizationCopyRights_send_message(xpc_object_t message
, AuthorizationRights
**authorizedRights
)
280 OSStatus status
= errAuthorizationInternal
;
281 xpc_object_t reply
= NULL
;
284 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
287 reply
= xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message
);
288 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
289 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
292 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
295 if (authorizedRights
&& status
== errAuthorizationSuccess
) {
296 xpc_object_t tmpItems
= xpc_dictionary_get_value(reply
, AUTH_XPC_OUT_ITEMS
);
297 AuthorizationRights
* grantedRights
= DeserializeItemSet(tmpItems
);
298 require_action(grantedRights
!= NULL
, done
, status
= errAuthorizationInternal
);
300 *authorizedRights
= grantedRights
;
304 xpc_release_safe(reply
);
309 _AuthorizationCopyRights_prepare_message(AuthorizationRef authorization
, const AuthorizationRights
*rights
, const AuthorizationEnvironment
*environment
, AuthorizationFlags flags
, xpc_object_t
*message_out
)
311 OSStatus status
= errAuthorizationInternal
;
312 AuthorizationBlob
*blob
= NULL
;
313 xpc_object_t message
= xpc_dictionary_create(NULL
, NULL
, 0);
314 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
316 require_action(authorization
!= NULL
, done
, status
= errAuthorizationInvalidRef
);
317 blob
= (AuthorizationBlob
*)authorization
;
319 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_COPY_RIGHTS
);
320 xpc_dictionary_set_data(message
, AUTH_XPC_BLOB
, blob
, sizeof(AuthorizationBlob
));
321 setItemSet(message
, AUTH_XPC_RIGHTS
, rights
);
322 setItemSet(message
, AUTH_XPC_ENVIRONMENT
, environment
);
323 xpc_dictionary_set_uint64(message
, AUTH_XPC_FLAGS
, flags
);
325 *message_out
= message
;
327 status
= errAuthorizationSuccess
;
330 xpc_release_safe(message
);
334 OSStatus
AuthorizationCopyRights(AuthorizationRef authorization
,
335 const AuthorizationRights
*rights
,
336 const AuthorizationEnvironment
*environment
,
337 AuthorizationFlags flags
,
338 AuthorizationRights
**authorizedRights
)
340 OSStatus status
= errAuthorizationInternal
;
341 xpc_object_t message
= NULL
;
343 require_noerr(status
= _AuthorizationCopyRights_prepare_message(authorization
, rights
, environment
, flags
, &message
), done
);
344 require_noerr(status
= _AuthorizationCopyRights_send_message(message
, authorizedRights
), done
);
347 xpc_release_safe(message
);
352 void AuthorizationCopyRightsAsync(AuthorizationRef authorization
,
353 const AuthorizationRights
*rights
,
354 const AuthorizationEnvironment
*environment
,
355 AuthorizationFlags flags
,
356 AuthorizationAsyncCallback callbackBlock
)
358 OSStatus prepare_status
= errAuthorizationInternal
;
359 __block xpc_object_t message
= NULL
;
361 prepare_status
= _AuthorizationCopyRights_prepare_message(authorization
, rights
, environment
, flags
, &message
);
362 if (prepare_status
!= errAuthorizationSuccess
) {
363 callbackBlock(prepare_status
, NULL
);
366 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^{
367 AuthorizationRights
*blockAuthorizedRights
= NULL
;
368 OSStatus status
= _AuthorizationCopyRights_send_message(message
, &blockAuthorizedRights
);
369 callbackBlock(status
, blockAuthorizedRights
);
370 xpc_release_safe(message
);
374 OSStatus
AuthorizationDismiss()
376 OSStatus status
= errAuthorizationInternal
;
377 xpc_object_t message
= NULL
;
378 xpc_object_t reply
= NULL
;
381 message
= xpc_dictionary_create(NULL
, NULL
, 0);
382 require(message
!= NULL
, done
);
384 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_DISMISS
);
387 reply
= xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message
);
388 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
389 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
392 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
395 xpc_release_safe(message
);
396 xpc_release_safe(reply
);
400 OSStatus
AuthorizationCopyInfo(AuthorizationRef authorization
,
401 AuthorizationString tag
,
402 AuthorizationItemSet
**info
)
404 OSStatus status
= errAuthorizationInternal
;
405 xpc_object_t message
= NULL
;
406 xpc_object_t reply
= NULL
;
407 AuthorizationBlob
*blob
= NULL
;
409 require_action(info
!= NULL
, done
, status
= errAuthorizationInvalidSet
);
410 require_action(authorization
!= NULL
, done
, status
= errAuthorizationInvalidRef
);
411 blob
= (AuthorizationBlob
*)authorization
;
414 message
= xpc_dictionary_create(NULL
, NULL
, 0);
415 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
417 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_COPY_INFO
);
418 xpc_dictionary_set_data(message
, AUTH_XPC_BLOB
, blob
, sizeof(AuthorizationBlob
));
420 xpc_dictionary_set_string(message
, AUTH_XPC_TAG
, tag
);
424 reply
= xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message
);
425 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
426 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
429 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
432 if (info
&& status
== errAuthorizationSuccess
) {
433 xpc_object_t tmpItems
= xpc_dictionary_get_value(reply
, AUTH_XPC_OUT_ITEMS
);
434 AuthorizationRights
* outInfo
= DeserializeItemSet(tmpItems
);
435 require_action(outInfo
!= NULL
, done
, status
= errAuthorizationInternal
);
441 xpc_release_safe(message
);
442 xpc_release_safe(reply
);
446 OSStatus
AuthorizationMakeExternalForm(AuthorizationRef authorization
,
447 AuthorizationExternalForm
*extForm
)
449 OSStatus status
= errAuthorizationInternal
;
450 xpc_object_t message
= NULL
;
451 xpc_object_t reply
= NULL
;
452 AuthorizationBlob
*blob
= NULL
;
454 require_action(extForm
!= NULL
, done
, status
= errAuthorizationInvalidPointer
);
455 require_action(authorization
!= NULL
, done
, status
= errAuthorizationInvalidRef
);
456 blob
= (AuthorizationBlob
*)authorization
;
459 message
= xpc_dictionary_create(NULL
, NULL
, 0);
460 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
462 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_MAKE_EXTERNAL_FORM
);
463 xpc_dictionary_set_data(message
, AUTH_XPC_BLOB
, blob
, sizeof(AuthorizationBlob
));
466 reply
= xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message
);
467 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
468 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
471 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
474 if (status
== errAuthorizationSuccess
) {
476 const void * data
= xpc_dictionary_get_data(reply
, AUTH_XPC_EXTERNAL
, &len
);
477 require_action(data
!= NULL
, done
, status
= errAuthorizationInternal
);
478 assert(len
== sizeof(AuthorizationExternalForm
));
480 *extForm
= *(AuthorizationExternalForm
*)data
;
484 xpc_release_safe(message
);
485 xpc_release_safe(reply
);
489 OSStatus
AuthorizationCreateFromExternalForm(const AuthorizationExternalForm
*extForm
,
490 AuthorizationRef
*authorization
)
492 OSStatus status
= errAuthorizationInternal
;
493 xpc_object_t message
= NULL
;
494 xpc_object_t reply
= NULL
;
496 require_action(extForm
!= NULL
, done
, status
= errAuthorizationInvalidPointer
);
497 require_action(authorization
!= NULL
, done
, status
= errAuthorizationInvalidRef
);
500 message
= xpc_dictionary_create(NULL
, NULL
, 0);
501 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
503 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_CREATE_FROM_EXTERNAL_FORM
);
504 xpc_dictionary_set_data(message
, AUTH_XPC_EXTERNAL
, extForm
, sizeof(AuthorizationExternalForm
));
507 reply
= xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message
);
508 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
509 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
512 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
515 if (authorization
&& status
== errAuthorizationSuccess
) {
517 const void * data
= xpc_dictionary_get_data(reply
, AUTH_XPC_BLOB
, &len
);
518 require_action(data
!= NULL
, done
, status
= errAuthorizationInternal
);
519 assert(len
== sizeof(AuthorizationBlob
));
521 AuthorizationBlob
* blob
= (AuthorizationBlob
*)calloc(1u, sizeof(AuthorizationBlob
));
522 require_action(blob
!= NULL
, done
, status
= errAuthorizationInternal
);
523 *blob
= *(AuthorizationBlob
*)data
;
525 *authorization
= (AuthorizationRef
)blob
;
529 xpc_release_safe(message
);
530 xpc_release_safe(reply
);
534 OSStatus
AuthorizationFreeItemSet(AuthorizationItemSet
*set
)
537 return errAuthorizationSuccess
;
540 OSStatus
AuthorizationEnableSmartCard(AuthorizationRef authRef
, Boolean enable
)
542 OSStatus status
= errAuthorizationInternal
;
543 xpc_object_t message
= NULL
;
544 xpc_object_t reply
= NULL
;
545 AuthorizationBlob
*blob
= NULL
;
548 message
= xpc_dictionary_create(NULL
, NULL
, 0);
549 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
550 require_action(authRef
!= NULL
, done
, status
= errAuthorizationInvalidRef
);
551 blob
= (AuthorizationBlob
*)authRef
;
552 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_ENABLE_SMARTCARD
);
553 xpc_dictionary_set_data(message
, AUTH_XPC_BLOB
, blob
, sizeof(AuthorizationBlob
));
554 xpc_dictionary_set_bool(message
, AUTH_XPC_DATA
, enable
);
557 reply
= xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message
);
558 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
559 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
561 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
564 xpc_release_safe(message
);
565 xpc_release_safe(reply
);
570 OSStatus
AuthorizationRightGet(const char *rightName
,
571 CFDictionaryRef
*rightDefinition
)
573 OSStatus status
= errAuthorizationInternal
;
574 xpc_object_t message
= NULL
;
575 xpc_object_t reply
= NULL
;
577 require_action(rightName
!= NULL
, done
, status
= errAuthorizationInvalidPointer
);
580 message
= xpc_dictionary_create(NULL
, NULL
, 0);
581 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
583 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_RIGHT_GET
);
584 xpc_dictionary_set_string(message
, AUTH_XPC_RIGHT_NAME
, rightName
);
587 reply
= xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message
);
588 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
589 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
592 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
595 if (rightDefinition
&& status
== errAuthorizationSuccess
) {
596 xpc_object_t value
= xpc_dictionary_get_value(reply
, AUTH_XPC_DATA
);
597 require_action(value
!= NULL
, done
, status
= errAuthorizationInternal
);
598 require_action(xpc_get_type(value
) == XPC_TYPE_DICTIONARY
, done
, status
= errAuthorizationInternal
);
600 CFTypeRef cfdict
= _CFXPCCreateCFObjectFromXPCObject(value
);
601 require_action(cfdict
!= NULL
, done
, status
= errAuthorizationInternal
);
603 *rightDefinition
= cfdict
;
607 xpc_release_safe(message
);
608 xpc_release_safe(reply
);
612 OSStatus
AuthorizationRightSet(AuthorizationRef authRef
,
613 const char *rightName
,
614 CFTypeRef rightDefinition
,
615 CFStringRef descriptionKey
,
617 CFStringRef tableName
)
619 OSStatus status
= errAuthorizationInternal
;
620 xpc_object_t message
= NULL
;
621 xpc_object_t reply
= NULL
;
622 AuthorizationBlob
*blob
= NULL
;
623 CFMutableDictionaryRef rightDict
= NULL
;
624 CFBundleRef clientBundle
= bundle
;
630 require_action(rightDefinition
!= NULL
, done
, status
= errAuthorizationInvalidPointer
);
631 require_action(rightName
!= NULL
, done
, status
= errAuthorizationInvalidPointer
);
632 require_action(authRef
!= NULL
, done
, status
= errAuthorizationInvalidRef
);
633 blob
= (AuthorizationBlob
*)authRef
;
636 message
= xpc_dictionary_create(NULL
, NULL
, 0);
637 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
639 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_RIGHT_SET
);
640 xpc_dictionary_set_data(message
, AUTH_XPC_BLOB
, blob
, sizeof(AuthorizationBlob
));
641 xpc_dictionary_set_string(message
, AUTH_XPC_RIGHT_NAME
, rightName
);
644 if (CFGetTypeID(rightDefinition
) == CFStringGetTypeID()) {
645 rightDict
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
646 require_action(rightDict
!= NULL
, done
, status
= errAuthorizationInternal
);
648 CFDictionarySetValue(rightDict
, CFSTR(kAuthorizationRightRule
), rightDefinition
);
650 } else if (CFGetTypeID(rightDefinition
) == CFDictionaryGetTypeID()) {
651 rightDict
= CFDictionaryCreateMutableCopy(kCFAllocatorDefault
, 0, rightDefinition
);
652 require_action(rightDict
!= NULL
, done
, status
= errAuthorizationInternal
);
655 status
= errAuthorizationInvalidPointer
;
660 if (descriptionKey
) {
661 CFMutableDictionaryRef locDict
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
662 require_action(locDict
!= NULL
, done
, status
= errAuthorizationInternal
);
664 if (clientBundle
== NULL
) {
665 clientBundle
= CFBundleGetMainBundle();
666 CFRetain(clientBundle
);
670 CFArrayRef bundleLocalizations
= CFBundleCopyBundleLocalizations(clientBundle
);
671 if (bundleLocalizations
) {
672 // for every CFString in localizations do
673 CFIndex locIndex
, allLocs
= CFArrayGetCount(bundleLocalizations
);
674 for (locIndex
= 0; locIndex
< allLocs
; locIndex
++)
676 CFStringRef oneLocalization
= (CFStringRef
)CFArrayGetValueAtIndex(bundleLocalizations
, locIndex
);
678 if (!oneLocalization
)
681 // @@@ no way to get "Localized" and "strings" as constants?
682 CFURLRef locURL
= CFBundleCopyResourceURLForLocalization(clientBundle
, tableName
? tableName
: CFSTR("Localizable"), CFSTR("strings"), NULL
/*subDirName*/, oneLocalization
);
687 CFDataRef tableData
= NULL
;
689 CFStringRef errStr
= NULL
;
690 CFPropertyListRef stringTable
= NULL
;
692 CFURLCreateDataAndPropertiesFromResource(CFGetAllocator(clientBundle
), locURL
, &tableData
, NULL
, NULL
, &errCode
);
693 CFReleaseSafe(locURL
);
696 CFReleaseSafe(tableData
);
700 stringTable
= CFPropertyListCreateFromXMLData(CFGetAllocator(clientBundle
), tableData
, kCFPropertyListImmutable
, &errStr
);
701 CFReleaseSafe(errStr
);
702 CFReleaseSafe(tableData
);
704 CFStringRef value
= (CFStringRef
)CFDictionaryGetValue(stringTable
, descriptionKey
);
705 if (value
== NULL
|| CFEqual(value
, CFSTR(""))) {
706 CFReleaseSafe(stringTable
);
709 // oneLocalization/value into our dictionary
710 CFDictionarySetValue(locDict
, oneLocalization
, value
);
711 CFReleaseSafe(stringTable
);
714 CFReleaseSafe(bundleLocalizations
);
718 // add the description as the default localization into the dictionary
719 CFDictionarySetValue(locDict
, CFSTR(""), descriptionKey
);
721 // stuff localization table into right definition
722 CFDictionarySetValue(rightDict
, CFSTR(kAuthorizationRuleParameterDefaultPrompt
), locDict
);
723 CFReleaseSafe(locDict
);
726 xpc_object_t value
= _CFXPCCreateXPCObjectFromCFObject(rightDict
);
727 xpc_dictionary_set_value(message
, AUTH_XPC_DATA
, value
);
728 xpc_release_safe(value
);
731 reply
= xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message
);
732 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
733 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
736 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
739 CFReleaseSafe(clientBundle
);
740 CFReleaseSafe(rightDict
);
741 xpc_release_safe(message
);
742 xpc_release_safe(reply
);
746 OSStatus
AuthorizationRightRemove(AuthorizationRef authorization
,
747 const char *rightName
)
749 OSStatus status
= errAuthorizationInternal
;
750 xpc_object_t message
= NULL
;
751 xpc_object_t reply
= NULL
;
752 AuthorizationBlob
*blob
= NULL
;
754 require_action(rightName
!= NULL
, done
, status
= errAuthorizationInvalidPointer
);
755 require_action(authorization
!= NULL
, done
, status
= errAuthorizationInvalidRef
);
756 blob
= (AuthorizationBlob
*)authorization
;
759 message
= xpc_dictionary_create(NULL
, NULL
, 0);
760 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
762 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_RIGHT_REMOVE
);
763 xpc_dictionary_set_data(message
, AUTH_XPC_BLOB
, blob
, sizeof(AuthorizationBlob
));
764 xpc_dictionary_set_string(message
, AUTH_XPC_RIGHT_NAME
, rightName
);
767 reply
= xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message
);
768 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
769 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
772 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
775 xpc_release_safe(message
);
776 xpc_release_safe(reply
);