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>
12 #include <utilities/SecDispatchRelease.h>
13 #include <utilities/SecCFRelease.h>
15 #include <xpc/private.h>
16 #include <mach/mach.h>
18 #include <AssertMacros.h>
19 #include <CoreFoundation/CFXPCBridge.h>
20 #include <CoreGraphics/CGWindow.h>
24 static os_log_t
AUTH_LOG_DEFAULT() {
25 static dispatch_once_t once
;
27 dispatch_once(&once
, ^{ log
= os_log_create("com.apple.Authorization", "framework"); });
31 #define AUTH_LOG AUTH_LOG_DEFAULT()
33 static dispatch_queue_t
34 get_authorization_dispatch_queue()
36 static dispatch_once_t onceToken
= 0;
37 static dispatch_queue_t connection_queue
= NULL
;
39 dispatch_once(&onceToken
, ^{
40 connection_queue
= dispatch_queue_create("authorization-connection-queue", DISPATCH_QUEUE_SERIAL
);
43 return connection_queue
;
46 static xpc_connection_t
47 get_authorization_connection()
49 static xpc_connection_t connection
= NULL
;
51 dispatch_sync(get_authorization_dispatch_queue(), ^{
52 if (connection
== NULL
) {
53 connection
= xpc_connection_create(SECURITY_AUTH_NAME
, NULL
);
56 syslog(LOG_ERR
, "Authorization, failed to create xpc connection to %s", SECURITY_AUTH_NAME
);
57 connection
= xpc_connection_create(SECURITY_AUTH_NAME
, NULL
);
60 xpc_connection_set_event_handler(connection
, ^(xpc_object_t event
) {
61 if (xpc_get_type(event
) == XPC_TYPE_ERROR
) {
62 if (event
== XPC_ERROR_CONNECTION_INVALID
) {
63 syslog(LOG_ERR
, "Authorization, server not available");
65 // XPC_ERROR_CONNECTION_INTERRUPTED
66 // XPC_ERROR_TERMINATION_IMMINENT
68 char * desc
= xpc_copy_description(event
);
69 syslog(LOG_ERR
, "Authorization, we should never get messages on this connection: %s", desc
);
74 xpc_connection_resume(connection
);
77 xpc_object_t message
= xpc_dictionary_create(NULL
, NULL
, 0);
78 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_SETUP
);
79 mach_port_t bootstrap
= MACH_PORT_NULL
;
80 task_get_bootstrap_port(mach_task_self(), &bootstrap
);
81 xpc_dictionary_set_mach_send(message
, AUTH_XPC_BOOTSTRAP
, bootstrap
);
82 xpc_object_t reply
= xpc_connection_send_message_with_reply_sync(connection
, message
);
83 xpc_release_safe(message
);
84 xpc_release_safe(reply
);
92 setItemSet(xpc_object_t message
, const char * key
, const AuthorizationItemSet
* itemSet
)
94 xpc_object_t serialized
= SerializeItemSet(itemSet
);
96 xpc_dictionary_set_value(message
, key
, serialized
);
97 xpc_release(serialized
);
101 OSStatus
AuthorizationCreate(const AuthorizationRights
*rights
,
102 const AuthorizationEnvironment
*environment
,
103 AuthorizationFlags flags
,
104 AuthorizationRef
*authorization
)
106 OSStatus status
= errAuthorizationInternal
;
107 xpc_object_t message
= NULL
;
108 xpc_object_t reply
= NULL
;
110 // require_action(!(rights == NULL && authorization == NULL), done, status = errAuthorizationInvalidSet);
113 message
= xpc_dictionary_create(NULL
, NULL
, 0);
114 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
116 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_CREATE
);
117 setItemSet(message
, AUTH_XPC_RIGHTS
, rights
);
118 setItemSet(message
, AUTH_XPC_ENVIRONMENT
, environment
);
119 xpc_dictionary_set_uint64(message
, AUTH_XPC_FLAGS
, flags
| (authorization
? 0 : kAuthorizationFlagNoData
));
122 reply
= xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message
);
123 require_action_quiet(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
124 require_action_quiet(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
;);
127 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
130 if (authorization
&& status
== errAuthorizationSuccess
) {
132 const void * data
= xpc_dictionary_get_data(reply
, AUTH_XPC_BLOB
, &len
);
133 require_action(data
!= NULL
, done
, status
= errAuthorizationInternal
);
134 assert(len
== sizeof(AuthorizationBlob
));
136 AuthorizationBlob
* blob
= (AuthorizationBlob
*)calloc(1u, sizeof(AuthorizationBlob
));
137 require_action(blob
!= NULL
, done
, status
= errAuthorizationInternal
);
138 *blob
= *(AuthorizationBlob
*)data
;
140 *authorization
= (AuthorizationRef
)blob
;
144 xpc_release_safe(message
);
145 xpc_release_safe(reply
);
149 OSStatus
AuthorizationCreateWithAuditToken(audit_token_t token
,
150 const AuthorizationEnvironment
*environment
,
151 AuthorizationFlags flags
,
152 AuthorizationRef
*authorization
)
154 OSStatus status
= errAuthorizationInternal
;
155 xpc_object_t message
= NULL
;
156 xpc_object_t reply
= NULL
;
158 require_action(authorization
!= NULL
, done
, status
= errAuthorizationInvalidPointer
);
161 message
= xpc_dictionary_create(NULL
, NULL
, 0);
162 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
164 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_CREATE_WITH_AUDIT_TOKEN
);
165 xpc_dictionary_set_data(message
, AUTH_XPC_DATA
, &token
, sizeof(token
));
166 setItemSet(message
, AUTH_XPC_ENVIRONMENT
, environment
);
167 xpc_dictionary_set_uint64(message
, AUTH_XPC_FLAGS
, flags
);
170 reply
= xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message
);
171 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
172 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
175 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
178 if (status
== errAuthorizationSuccess
) {
180 const void * data
= xpc_dictionary_get_data(reply
, AUTH_XPC_BLOB
, &len
);
181 require_action(data
!= NULL
, done
, status
= errAuthorizationInternal
);
182 assert(len
== sizeof(AuthorizationBlob
));
184 AuthorizationBlob
* blob
= (AuthorizationBlob
*)calloc(1u, sizeof(AuthorizationBlob
));
185 require_action(blob
!= NULL
, done
, status
= errAuthorizationInternal
);
186 *blob
= *(AuthorizationBlob
*)data
;
188 *authorization
= (AuthorizationRef
)blob
;
192 xpc_release_safe(message
);
193 xpc_release_safe(reply
);
197 OSStatus
AuthorizationFree(AuthorizationRef authorization
, AuthorizationFlags flags
)
199 OSStatus status
= errAuthorizationInternal
;
200 xpc_object_t message
= NULL
;
201 xpc_object_t reply
= NULL
;
202 AuthorizationBlob
*blob
= NULL
;
204 require_action(authorization
!= NULL
, done
, status
= errAuthorizationInvalidRef
);
205 blob
= (AuthorizationBlob
*)authorization
;
208 message
= xpc_dictionary_create(NULL
, NULL
, 0);
209 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
211 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_FREE
);
212 xpc_dictionary_set_data(message
, AUTH_XPC_BLOB
, blob
, sizeof(AuthorizationBlob
));
213 xpc_dictionary_set_uint64(message
, AUTH_XPC_FLAGS
, flags
);
216 reply
= xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message
);
217 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
218 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
221 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
227 xpc_release_safe(message
);
228 xpc_release_safe(reply
);
233 _AuthorizationPreauthorizeCredentials_send_message(xpc_object_t message
)
235 OSStatus status
= errAuthorizationInternal
;
236 xpc_object_t reply
= NULL
;
239 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
242 reply
= xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message
);
243 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
244 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
247 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
250 xpc_release_safe(reply
);
255 _AuthorizationPreauthorizeCredentials_prepare_message(AuthorizationRef authorization
, const AuthorizationItemSet
*credentials
, xpc_object_t
*message_out
)
257 OSStatus status
= errAuthorizationInternal
;
258 AuthorizationBlob
*blob
= NULL
;
259 xpc_object_t message
= xpc_dictionary_create(NULL
, NULL
, 0);
260 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
262 require_action(authorization
!= NULL
, done
, status
= errAuthorizationInvalidRef
);
263 blob
= (AuthorizationBlob
*)authorization
;
265 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_PREAUTHORIZE_CREDENTIALS
);
266 xpc_dictionary_set_data(message
, AUTH_XPC_BLOB
, blob
, sizeof(AuthorizationBlob
));
267 setItemSet(message
, AUTH_XPC_DATA
, credentials
);
269 *message_out
= message
;
271 status
= errAuthorizationSuccess
;
274 xpc_release_safe(message
);
278 OSStatus
AuthorizationPreauthorizeCredentials(AuthorizationRef authorization
, const AuthorizationItemSet
*credentials
)
280 OSStatus status
= errAuthorizationInternal
;
281 xpc_object_t message
= NULL
;
283 require_noerr(status
= _AuthorizationPreauthorizeCredentials_prepare_message(authorization
, credentials
, &message
), done
);
284 require_noerr(status
= _AuthorizationPreauthorizeCredentials_send_message(message
), done
);
287 xpc_release_safe(message
);
292 _AuthorizationCopyRights_send_message(xpc_object_t message
, AuthorizationRights
**authorizedRights
)
294 OSStatus status
= errAuthorizationInternal
;
295 xpc_object_t reply
= NULL
;
298 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
301 reply
= xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message
);
302 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
303 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
306 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
309 if (authorizedRights
&& status
== errAuthorizationSuccess
) {
310 xpc_object_t tmpItems
= xpc_dictionary_get_value(reply
, AUTH_XPC_OUT_ITEMS
);
311 AuthorizationRights
* grantedRights
= DeserializeItemSet(tmpItems
);
312 require_action(grantedRights
!= NULL
, done
, status
= errAuthorizationInternal
);
314 *authorizedRights
= grantedRights
;
318 xpc_release_safe(reply
);
323 _AuthorizationCopyRights_prepare_message(AuthorizationRef authorization
, const AuthorizationRights
*rights
, const AuthorizationEnvironment
*environment
, AuthorizationFlags flags
, xpc_object_t
*message_out
)
325 OSStatus status
= errAuthorizationInternal
;
326 AuthorizationBlob
*blob
= NULL
;
327 xpc_object_t message
= xpc_dictionary_create(NULL
, NULL
, 0);
328 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
330 require_action(authorization
!= NULL
, done
, status
= errAuthorizationInvalidRef
);
331 blob
= (AuthorizationBlob
*)authorization
;
333 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_COPY_RIGHTS
);
334 xpc_dictionary_set_data(message
, AUTH_XPC_BLOB
, blob
, sizeof(AuthorizationBlob
));
335 setItemSet(message
, AUTH_XPC_RIGHTS
, rights
);
336 setItemSet(message
, AUTH_XPC_ENVIRONMENT
, environment
);
337 xpc_dictionary_set_uint64(message
, AUTH_XPC_FLAGS
, flags
);
339 *message_out
= message
;
341 status
= errAuthorizationSuccess
;
344 xpc_release_safe(message
);
348 OSStatus
AuthorizationCopyRights(AuthorizationRef authorization
,
349 const AuthorizationRights
*rights
,
350 const AuthorizationEnvironment
*environment
,
351 AuthorizationFlags flags
,
352 AuthorizationRights
**authorizedRights
)
354 OSStatus status
= errAuthorizationInternal
;
356 if ((flags
& kAuthorizationFlagSheet
) && environment
) {
357 // check if window ID is present in environment
358 CGWindowID window
= 0;
359 for (UInt32 i
= 0; i
< environment
->count
; ++i
) {
360 if (strncmp(environment
->items
[i
].name
, kAuthorizationEnvironmentWindowId
, strlen(kAuthorizationEnvironmentWindowId
)) == 0
361 && (environment
->items
[i
].valueLength
= sizeof(window
)) && environment
->items
[i
].value
) {
362 window
= *(CGWindowID
*)environment
->items
[i
].value
;
367 os_log_debug(AUTH_LOG
, "Trying to use sheet version");
368 static OSStatus (*sheetAuthorizationWorker
)(CGWindowID windowID
, AuthorizationRef authorization
,
369 const AuthorizationRights
*rights
,
370 const AuthorizationEnvironment
*environment
,
371 AuthorizationFlags flags
,
372 AuthorizationRights
**authorizedRights
,
373 Boolean
*authorizationLaunched
) = NULL
;
374 static dispatch_once_t onceToken
;
375 dispatch_once(&onceToken
, ^{
376 void *handle
= dlopen("/System/Library/Frameworks/SecurityInterface.framework/SecurityInterface", RTLD_NOW
|RTLD_GLOBAL
|RTLD_NODELETE
);
378 sheetAuthorizationWorker
= dlsym(handle
, "sheetAuthorizationWorker");
382 if (sheetAuthorizationWorker
) {
383 Boolean authorizationLaunched
;
384 status
= sheetAuthorizationWorker(window
, authorization
, rights
, environment
, flags
, authorizedRights
, &authorizationLaunched
);
385 if (authorizationLaunched
== true) {
386 os_log_debug(AUTH_LOG
, "Returning sheet result %d", (int)status
);
389 os_log(AUTH_LOG
, "Sheet authorization cannot be used this time, falling back to the SecurityAgent UI");
391 os_log_debug(AUTH_LOG
, "Failed to find sheet support in SecurityInterface");
393 // fall back to the standard (windowed) version if sheets are not available
397 xpc_object_t message
= NULL
;
399 require_noerr(status
= _AuthorizationCopyRights_prepare_message(authorization
, rights
, environment
, flags
, &message
), done
);
400 require_noerr(status
= _AuthorizationCopyRights_send_message(message
, authorizedRights
), done
);
403 xpc_release_safe(message
);
408 void AuthorizationCopyRightsAsync(AuthorizationRef authorization
,
409 const AuthorizationRights
*rights
,
410 const AuthorizationEnvironment
*environment
,
411 AuthorizationFlags flags
,
412 AuthorizationAsyncCallback callbackBlock
)
414 OSStatus prepare_status
= errAuthorizationInternal
;
415 __block xpc_object_t message
= NULL
;
417 prepare_status
= _AuthorizationCopyRights_prepare_message(authorization
, rights
, environment
, flags
, &message
);
418 if (prepare_status
!= errAuthorizationSuccess
) {
419 callbackBlock(prepare_status
, NULL
);
422 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^{
423 AuthorizationRights
*blockAuthorizedRights
= NULL
;
424 OSStatus status
= _AuthorizationCopyRights_send_message(message
, &blockAuthorizedRights
);
425 callbackBlock(status
, blockAuthorizedRights
);
426 xpc_release_safe(message
);
430 OSStatus
AuthorizationDismiss()
432 OSStatus status
= errAuthorizationInternal
;
433 xpc_object_t message
= NULL
;
434 xpc_object_t reply
= NULL
;
437 message
= xpc_dictionary_create(NULL
, NULL
, 0);
438 require(message
!= NULL
, done
);
440 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_DISMISS
);
443 reply
= xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message
);
444 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
445 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
448 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
451 xpc_release_safe(message
);
452 xpc_release_safe(reply
);
456 OSStatus
AuthorizationCopyInfo(AuthorizationRef authorization
,
457 AuthorizationString tag
,
458 AuthorizationItemSet
**info
)
460 OSStatus status
= errAuthorizationInternal
;
461 xpc_object_t message
= NULL
;
462 xpc_object_t reply
= NULL
;
463 AuthorizationBlob
*blob
= NULL
;
465 require_action(info
!= NULL
, done
, status
= errAuthorizationInvalidSet
);
466 require_action(authorization
!= NULL
, done
, status
= errAuthorizationInvalidRef
);
467 blob
= (AuthorizationBlob
*)authorization
;
470 message
= xpc_dictionary_create(NULL
, NULL
, 0);
471 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
473 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_COPY_INFO
);
474 xpc_dictionary_set_data(message
, AUTH_XPC_BLOB
, blob
, sizeof(AuthorizationBlob
));
476 xpc_dictionary_set_string(message
, AUTH_XPC_TAG
, tag
);
480 reply
= xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message
);
481 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
482 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
485 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
488 if (info
&& status
== errAuthorizationSuccess
) {
489 xpc_object_t tmpItems
= xpc_dictionary_get_value(reply
, AUTH_XPC_OUT_ITEMS
);
490 AuthorizationRights
* outInfo
= DeserializeItemSet(tmpItems
);
491 require_action(outInfo
!= NULL
, done
, status
= errAuthorizationInternal
);
497 xpc_release_safe(message
);
498 xpc_release_safe(reply
);
502 OSStatus
AuthorizationMakeExternalForm(AuthorizationRef authorization
,
503 AuthorizationExternalForm
*extForm
)
505 OSStatus status
= errAuthorizationInternal
;
506 xpc_object_t message
= NULL
;
507 xpc_object_t reply
= NULL
;
508 AuthorizationBlob
*blob
= NULL
;
510 require_action(extForm
!= NULL
, done
, status
= errAuthorizationInvalidPointer
);
511 require_action(authorization
!= NULL
, done
, status
= errAuthorizationInvalidRef
);
512 blob
= (AuthorizationBlob
*)authorization
;
515 message
= xpc_dictionary_create(NULL
, NULL
, 0);
516 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
518 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_MAKE_EXTERNAL_FORM
);
519 xpc_dictionary_set_data(message
, AUTH_XPC_BLOB
, blob
, sizeof(AuthorizationBlob
));
522 reply
= xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message
);
523 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
524 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
527 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
530 if (status
== errAuthorizationSuccess
) {
532 const void * data
= xpc_dictionary_get_data(reply
, AUTH_XPC_EXTERNAL
, &len
);
533 require_action(data
!= NULL
, done
, status
= errAuthorizationInternal
);
534 assert(len
== sizeof(AuthorizationExternalForm
));
536 *extForm
= *(AuthorizationExternalForm
*)data
;
540 xpc_release_safe(message
);
541 xpc_release_safe(reply
);
545 OSStatus
AuthorizationCreateFromExternalForm(const AuthorizationExternalForm
*extForm
,
546 AuthorizationRef
*authorization
)
548 OSStatus status
= errAuthorizationInternal
;
549 xpc_object_t message
= NULL
;
550 xpc_object_t reply
= NULL
;
552 require_action(extForm
!= NULL
, done
, status
= errAuthorizationInvalidPointer
);
553 require_action(authorization
!= NULL
, done
, status
= errAuthorizationInvalidRef
);
556 message
= xpc_dictionary_create(NULL
, NULL
, 0);
557 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
559 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_CREATE_FROM_EXTERNAL_FORM
);
560 xpc_dictionary_set_data(message
, AUTH_XPC_EXTERNAL
, extForm
, sizeof(AuthorizationExternalForm
));
563 reply
= xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message
);
564 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
565 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
568 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
571 if (authorization
&& status
== errAuthorizationSuccess
) {
573 const void * data
= xpc_dictionary_get_data(reply
, AUTH_XPC_BLOB
, &len
);
574 require_action(data
!= NULL
, done
, status
= errAuthorizationInternal
);
575 assert(len
== sizeof(AuthorizationBlob
));
577 AuthorizationBlob
* blob
= (AuthorizationBlob
*)calloc(1u, sizeof(AuthorizationBlob
));
578 require_action(blob
!= NULL
, done
, status
= errAuthorizationInternal
);
579 *blob
= *(AuthorizationBlob
*)data
;
581 *authorization
= (AuthorizationRef
)blob
;
585 xpc_release_safe(message
);
586 xpc_release_safe(reply
);
590 OSStatus
AuthorizationFreeItemSet(AuthorizationItemSet
*set
)
593 return errAuthorizationSuccess
;
596 OSStatus
AuthorizationEnableSmartCard(AuthorizationRef authRef
, Boolean enable
)
598 OSStatus status
= errAuthorizationInternal
;
599 xpc_object_t message
= NULL
;
600 xpc_object_t reply
= NULL
;
601 AuthorizationBlob
*blob
= NULL
;
604 message
= xpc_dictionary_create(NULL
, NULL
, 0);
605 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
606 require_action(authRef
!= NULL
, done
, status
= errAuthorizationInvalidRef
);
607 blob
= (AuthorizationBlob
*)authRef
;
608 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_ENABLE_SMARTCARD
);
609 xpc_dictionary_set_data(message
, AUTH_XPC_BLOB
, blob
, sizeof(AuthorizationBlob
));
610 xpc_dictionary_set_bool(message
, AUTH_XPC_DATA
, enable
);
613 reply
= xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message
);
614 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
615 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
617 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
620 xpc_release_safe(message
);
621 xpc_release_safe(reply
);
626 OSStatus
AuthorizationRightGet(const char *rightName
,
627 CFDictionaryRef
*rightDefinition
)
629 OSStatus status
= errAuthorizationInternal
;
630 xpc_object_t message
= NULL
;
631 xpc_object_t reply
= NULL
;
633 require_action(rightName
!= NULL
, done
, status
= errAuthorizationInvalidPointer
);
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_GET
);
640 xpc_dictionary_set_string(message
, AUTH_XPC_RIGHT_NAME
, rightName
);
643 reply
= xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message
);
644 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
645 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
648 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
651 if (rightDefinition
&& status
== errAuthorizationSuccess
) {
652 xpc_object_t value
= xpc_dictionary_get_value(reply
, AUTH_XPC_DATA
);
653 require_action(value
!= NULL
, done
, status
= errAuthorizationInternal
);
654 require_action(xpc_get_type(value
) == XPC_TYPE_DICTIONARY
, done
, status
= errAuthorizationInternal
);
656 CFTypeRef cfdict
= _CFXPCCreateCFObjectFromXPCObject(value
);
657 require_action(cfdict
!= NULL
, done
, status
= errAuthorizationInternal
);
659 *rightDefinition
= cfdict
;
663 xpc_release_safe(message
);
664 xpc_release_safe(reply
);
668 OSStatus
AuthorizationRightSet(AuthorizationRef authRef
,
669 const char *rightName
,
670 CFTypeRef rightDefinition
,
671 CFStringRef descriptionKey
,
673 CFStringRef tableName
)
675 OSStatus status
= errAuthorizationInternal
;
676 xpc_object_t message
= NULL
;
677 xpc_object_t reply
= NULL
;
678 AuthorizationBlob
*blob
= NULL
;
679 CFMutableDictionaryRef rightDict
= NULL
;
680 CFBundleRef clientBundle
= bundle
;
686 require_action(rightDefinition
!= NULL
, done
, status
= errAuthorizationInvalidPointer
);
687 require_action(rightName
!= NULL
, done
, status
= errAuthorizationInvalidPointer
);
688 require_action(authRef
!= NULL
, done
, status
= errAuthorizationInvalidRef
);
689 blob
= (AuthorizationBlob
*)authRef
;
692 message
= xpc_dictionary_create(NULL
, NULL
, 0);
693 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
695 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_RIGHT_SET
);
696 xpc_dictionary_set_data(message
, AUTH_XPC_BLOB
, blob
, sizeof(AuthorizationBlob
));
697 xpc_dictionary_set_string(message
, AUTH_XPC_RIGHT_NAME
, rightName
);
700 if (CFGetTypeID(rightDefinition
) == CFStringGetTypeID()) {
701 rightDict
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
702 require_action(rightDict
!= NULL
, done
, status
= errAuthorizationInternal
);
704 CFDictionarySetValue(rightDict
, CFSTR(kAuthorizationRightRule
), rightDefinition
);
706 } else if (CFGetTypeID(rightDefinition
) == CFDictionaryGetTypeID()) {
707 rightDict
= CFDictionaryCreateMutableCopy(kCFAllocatorDefault
, 0, rightDefinition
);
708 require_action(rightDict
!= NULL
, done
, status
= errAuthorizationInternal
);
711 status
= errAuthorizationInvalidPointer
;
716 if (descriptionKey
) {
717 CFMutableDictionaryRef locDict
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
718 require_action(locDict
!= NULL
, done
, status
= errAuthorizationInternal
);
720 if (clientBundle
== NULL
) {
721 clientBundle
= CFBundleGetMainBundle();
722 CFRetain(clientBundle
);
726 CFArrayRef bundleLocalizations
= CFBundleCopyBundleLocalizations(clientBundle
);
727 if (bundleLocalizations
) {
728 // for every CFString in localizations do
729 CFIndex locIndex
, allLocs
= CFArrayGetCount(bundleLocalizations
);
730 for (locIndex
= 0; locIndex
< allLocs
; locIndex
++)
732 CFStringRef oneLocalization
= (CFStringRef
)CFArrayGetValueAtIndex(bundleLocalizations
, locIndex
);
734 if (!oneLocalization
)
737 // @@@ no way to get "Localized" and "strings" as constants?
738 CFURLRef locURL
= CFBundleCopyResourceURLForLocalization(clientBundle
, tableName
? tableName
: CFSTR("Localizable"), CFSTR("strings"), NULL
/*subDirName*/, oneLocalization
);
743 CFDataRef tableData
= NULL
;
745 CFStringRef errStr
= NULL
;
746 CFPropertyListRef stringTable
= NULL
;
748 CFURLCreateDataAndPropertiesFromResource(CFGetAllocator(clientBundle
), locURL
, &tableData
, NULL
, NULL
, &errCode
);
749 CFReleaseSafe(locURL
);
752 CFReleaseSafe(tableData
);
756 stringTable
= CFPropertyListCreateFromXMLData(CFGetAllocator(clientBundle
), tableData
, kCFPropertyListImmutable
, &errStr
);
757 CFReleaseSafe(errStr
);
758 CFReleaseSafe(tableData
);
760 CFStringRef value
= (CFStringRef
)CFDictionaryGetValue(stringTable
, descriptionKey
);
761 if (value
== NULL
|| CFEqual(value
, CFSTR(""))) {
762 CFReleaseSafe(stringTable
);
765 // oneLocalization/value into our dictionary
766 CFDictionarySetValue(locDict
, oneLocalization
, value
);
767 CFReleaseSafe(stringTable
);
770 CFReleaseSafe(bundleLocalizations
);
774 // add the description as the default localization into the dictionary
775 CFDictionarySetValue(locDict
, CFSTR(""), descriptionKey
);
777 // stuff localization table into right definition
778 CFDictionarySetValue(rightDict
, CFSTR(kAuthorizationRuleParameterDefaultPrompt
), locDict
);
779 CFReleaseSafe(locDict
);
782 xpc_object_t value
= _CFXPCCreateXPCObjectFromCFObject(rightDict
);
783 xpc_dictionary_set_value(message
, AUTH_XPC_DATA
, value
);
784 xpc_release_safe(value
);
787 reply
= xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message
);
788 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
789 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
792 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
795 CFReleaseSafe(clientBundle
);
796 CFReleaseSafe(rightDict
);
797 xpc_release_safe(message
);
798 xpc_release_safe(reply
);
802 OSStatus
AuthorizationRightRemove(AuthorizationRef authorization
,
803 const char *rightName
)
805 OSStatus status
= errAuthorizationInternal
;
806 xpc_object_t message
= NULL
;
807 xpc_object_t reply
= NULL
;
808 AuthorizationBlob
*blob
= NULL
;
810 require_action(rightName
!= NULL
, done
, status
= errAuthorizationInvalidPointer
);
811 require_action(authorization
!= NULL
, done
, status
= errAuthorizationInvalidRef
);
812 blob
= (AuthorizationBlob
*)authorization
;
815 message
= xpc_dictionary_create(NULL
, NULL
, 0);
816 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
818 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_RIGHT_REMOVE
);
819 xpc_dictionary_set_data(message
, AUTH_XPC_BLOB
, blob
, sizeof(AuthorizationBlob
));
820 xpc_dictionary_set_string(message
, AUTH_XPC_RIGHT_NAME
, rightName
);
823 reply
= xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message
);
824 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
825 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
828 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
831 xpc_release_safe(message
);
832 xpc_release_safe(reply
);