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>
17 #include <AssertMacros.h>
18 #include <CoreFoundation/CFXPCBridge.h>
19 #include <CoreGraphics/CGWindow.h>
23 static os_log_t
AUTH_LOG_DEFAULT() {
24 static dispatch_once_t once
;
26 dispatch_once(&once
, ^{ log
= os_log_create("com.apple.Authorization", "framework"); });
30 #define AUTH_LOG AUTH_LOG_DEFAULT()
32 static dispatch_queue_t
33 get_authorization_dispatch_queue()
35 static dispatch_once_t onceToken
= 0;
36 static dispatch_queue_t connection_queue
= NULL
;
38 dispatch_once(&onceToken
, ^{
39 connection_queue
= dispatch_queue_create("authorization-connection-queue", DISPATCH_QUEUE_SERIAL
);
42 return connection_queue
;
45 static xpc_connection_t
46 get_authorization_connection()
48 static xpc_connection_t connection
= NULL
;
50 dispatch_sync(get_authorization_dispatch_queue(), ^{
51 if (connection
== NULL
) {
52 connection
= xpc_connection_create(SECURITY_AUTH_NAME
, NULL
);
55 os_log_error(AUTH_LOG
, "Failed to create xpc connection to %s", SECURITY_AUTH_NAME
);
56 connection
= xpc_connection_create(SECURITY_AUTH_NAME
, NULL
);
59 if (connection
== NULL
) {
60 os_log_error(AUTH_LOG
, "Still failed to create xpc connection to %s", SECURITY_AUTH_NAME
);
63 xpc_connection_set_event_handler(connection
, ^(xpc_object_t event
) {
64 if (xpc_get_type(event
) == XPC_TYPE_ERROR
) {
65 if (event
== XPC_ERROR_CONNECTION_INVALID
) {
66 os_log_error(AUTH_LOG
, "Server not available");
68 // XPC_ERROR_CONNECTION_INTERRUPTED
69 // XPC_ERROR_TERMINATION_IMMINENT
71 char * desc
= xpc_copy_description(event
);
72 os_log_error(AUTH_LOG
, "We should never get messages on this connection: %s", desc
);
77 xpc_connection_resume(connection
);
80 xpc_object_t message
= xpc_dictionary_create(NULL
, NULL
, 0);
81 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_SETUP
);
82 mach_port_t bootstrap
= MACH_PORT_NULL
;
83 task_get_bootstrap_port(mach_task_self(), &bootstrap
);
84 xpc_dictionary_set_mach_send(message
, AUTH_XPC_BOOTSTRAP
, bootstrap
);
85 xpc_object_t reply
= xpc_connection_send_message_with_reply_sync(connection
, message
);
86 xpc_release_safe(message
);
87 xpc_release_safe(reply
);
95 setItemSet(xpc_object_t message
, const char * key
, const AuthorizationItemSet
* itemSet
)
97 xpc_object_t serialized
= SerializeItemSet(itemSet
);
99 xpc_dictionary_set_value(message
, key
, serialized
);
100 xpc_release(serialized
);
104 OSStatus
AuthorizationCreate(const AuthorizationRights
*rights
,
105 const AuthorizationEnvironment
*environment
,
106 AuthorizationFlags flags
,
107 AuthorizationRef
*authorization
)
109 OSStatus status
= errAuthorizationInternal
;
110 xpc_object_t message
= NULL
;
111 xpc_object_t reply
= NULL
;
113 // require_action(!(rights == NULL && authorization == NULL), done, status = errAuthorizationInvalidSet);
116 message
= xpc_dictionary_create(NULL
, NULL
, 0);
117 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
119 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_CREATE
);
120 setItemSet(message
, AUTH_XPC_RIGHTS
, rights
);
121 setItemSet(message
, AUTH_XPC_ENVIRONMENT
, environment
);
122 xpc_dictionary_set_uint64(message
, AUTH_XPC_FLAGS
, flags
| (authorization
? 0 : kAuthorizationFlagNoData
));
125 xpc_connection_t conn
= get_authorization_connection();
126 require_action(conn
!= NULL
, done
, status
= errAuthorizationInternal
);
127 reply
= xpc_connection_send_message_with_reply_sync(conn
, message
);
128 require_action_quiet(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
129 require_action_quiet(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
;);
132 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
135 if (authorization
&& status
== errAuthorizationSuccess
) {
137 const void * data
= xpc_dictionary_get_data(reply
, AUTH_XPC_BLOB
, &len
);
138 require_action(data
!= NULL
, done
, status
= errAuthorizationInternal
);
139 require_action(len
== sizeof(AuthorizationBlob
), done
, status
= errAuthorizationInternal
);
141 AuthorizationBlob
* blob
= (AuthorizationBlob
*)calloc(1u, sizeof(AuthorizationBlob
));
142 require_action(blob
!= NULL
, done
, status
= errAuthorizationInternal
);
143 *blob
= *(AuthorizationBlob
*)data
;
145 *authorization
= (AuthorizationRef
)blob
;
149 xpc_release_safe(message
);
150 xpc_release_safe(reply
);
154 OSStatus
AuthorizationCreateWithAuditToken(audit_token_t token
,
155 const AuthorizationEnvironment
*environment
,
156 AuthorizationFlags flags
,
157 AuthorizationRef
*authorization
)
159 OSStatus status
= errAuthorizationInternal
;
160 xpc_object_t message
= NULL
;
161 xpc_object_t reply
= NULL
;
163 require_action(authorization
!= NULL
, done
, status
= errAuthorizationInvalidPointer
);
166 message
= xpc_dictionary_create(NULL
, NULL
, 0);
167 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
169 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_CREATE_WITH_AUDIT_TOKEN
);
170 xpc_dictionary_set_data(message
, AUTH_XPC_DATA
, &token
, sizeof(token
));
171 setItemSet(message
, AUTH_XPC_ENVIRONMENT
, environment
);
172 xpc_dictionary_set_uint64(message
, AUTH_XPC_FLAGS
, flags
);
175 xpc_connection_t conn
= get_authorization_connection();
176 require_action(conn
!= NULL
, done
, status
= errAuthorizationInternal
);
177 reply
= xpc_connection_send_message_with_reply_sync(conn
, message
);
178 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
179 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
182 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
185 if (status
== errAuthorizationSuccess
) {
187 const void * data
= xpc_dictionary_get_data(reply
, AUTH_XPC_BLOB
, &len
);
188 require_action(data
!= NULL
, done
, status
= errAuthorizationInternal
);
189 require_action(len
== sizeof(AuthorizationBlob
), done
, status
= errAuthorizationInternal
);
191 AuthorizationBlob
* blob
= (AuthorizationBlob
*)calloc(1u, sizeof(AuthorizationBlob
));
192 require_action(blob
!= NULL
, done
, status
= errAuthorizationInternal
);
193 *blob
= *(AuthorizationBlob
*)data
;
195 *authorization
= (AuthorizationRef
)blob
;
199 xpc_release_safe(message
);
200 xpc_release_safe(reply
);
204 OSStatus
AuthorizationFree(AuthorizationRef authorization
, AuthorizationFlags flags
)
206 OSStatus status
= errAuthorizationInternal
;
207 xpc_object_t message
= NULL
;
208 xpc_object_t reply
= NULL
;
209 AuthorizationBlob
*blob
= NULL
;
211 require_action(authorization
!= NULL
, done
, status
= errAuthorizationInvalidRef
);
212 blob
= (AuthorizationBlob
*)authorization
;
215 message
= xpc_dictionary_create(NULL
, NULL
, 0);
216 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
218 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_FREE
);
219 xpc_dictionary_set_data(message
, AUTH_XPC_BLOB
, blob
, sizeof(AuthorizationBlob
));
220 xpc_dictionary_set_uint64(message
, AUTH_XPC_FLAGS
, flags
);
223 xpc_connection_t conn
= get_authorization_connection();
224 require_action(conn
!= NULL
, done
, status
= errAuthorizationInternal
);
225 reply
= xpc_connection_send_message_with_reply_sync(conn
, message
);
226 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
227 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
230 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
236 xpc_release_safe(message
);
237 xpc_release_safe(reply
);
241 OSStatus
AuthorizationCopyRightProperties(const char *rightName
, CFDictionaryRef
*output
)
243 OSStatus status
= errAuthorizationInternal
;
244 xpc_object_t reply
= NULL
;
245 CFDataRef data
= NULL
;
246 xpc_object_t message
= NULL
;
247 require_action(rightName
!= NULL
, done
, status
= errAuthorizationInvalidPointer
);
249 message
= xpc_dictionary_create(NULL
, NULL
, 0);
250 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
252 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_COPY_RIGHT_PROPERTIES
);
253 xpc_dictionary_set_string(message
, AUTH_XPC_RIGHT_NAME
, rightName
);
255 xpc_connection_t conn
= get_authorization_connection();
256 require_action(conn
!= NULL
, done
, status
= errAuthorizationInternal
);
257 reply
= xpc_connection_send_message_with_reply_sync(conn
, message
);
258 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
259 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
262 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
263 if (output
&& status
== errAuthorizationSuccess
) {
265 const void *bytes
= xpc_dictionary_get_data(reply
, AUTH_XPC_OUT_ITEMS
, &len
);
266 data
= CFDataCreate(kCFAllocatorDefault
, bytes
, len
);
267 require_action(data
!= NULL
, done
, status
= errAuthorizationInternal
);
268 *output
= CFPropertyListCreateWithData(kCFAllocatorDefault
, data
, kCFPropertyListImmutable
, NULL
, NULL
);
271 xpc_release_safe(message
);
272 xpc_release_safe(reply
);
279 _AuthorizationCopyRights_send_message(xpc_object_t message
, AuthorizationRights
**authorizedRights
)
281 OSStatus status
= errAuthorizationInternal
;
282 xpc_object_t reply
= NULL
;
285 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
288 xpc_connection_t conn
= get_authorization_connection();
289 require_action(conn
!= NULL
, done
, status
= errAuthorizationInternal
);
290 reply
= xpc_connection_send_message_with_reply_sync(conn
, message
);
291 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
292 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
295 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
298 if (authorizedRights
&& status
== errAuthorizationSuccess
) {
299 xpc_object_t tmpItems
= xpc_dictionary_get_value(reply
, AUTH_XPC_OUT_ITEMS
);
300 AuthorizationRights
* grantedRights
= DeserializeItemSet(tmpItems
);
301 require_action(grantedRights
!= NULL
, done
, status
= errAuthorizationInternal
);
303 *authorizedRights
= grantedRights
;
307 xpc_release_safe(reply
);
312 _AuthorizationCopyRights_prepare_message(AuthorizationRef authorization
, const AuthorizationRights
*rights
, const AuthorizationEnvironment
*environment
, AuthorizationFlags flags
, xpc_object_t
*message_out
)
314 OSStatus status
= errAuthorizationInternal
;
315 AuthorizationBlob
*blob
= NULL
;
316 xpc_object_t message
= xpc_dictionary_create(NULL
, NULL
, 0);
317 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
319 require_action(authorization
!= NULL
, done
, status
= errAuthorizationInvalidRef
);
320 blob
= (AuthorizationBlob
*)authorization
;
322 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_COPY_RIGHTS
);
323 xpc_dictionary_set_data(message
, AUTH_XPC_BLOB
, blob
, sizeof(AuthorizationBlob
));
324 setItemSet(message
, AUTH_XPC_RIGHTS
, rights
);
325 setItemSet(message
, AUTH_XPC_ENVIRONMENT
, environment
);
326 xpc_dictionary_set_uint64(message
, AUTH_XPC_FLAGS
, flags
);
328 *message_out
= message
;
330 status
= errAuthorizationSuccess
;
333 xpc_release_safe(message
);
337 OSStatus
AuthorizationCopyRights(AuthorizationRef authorization
,
338 const AuthorizationRights
*rights
,
339 const AuthorizationEnvironment
*environment
,
340 AuthorizationFlags flags
,
341 AuthorizationRights
**authorizedRights
)
343 OSStatus status
= errAuthorizationInternal
;
345 if ((flags
& kAuthorizationFlagSheet
) && environment
) {
346 // check if window ID is present in environment
347 CGWindowID window
= 0;
348 for (UInt32 i
= 0; i
< environment
->count
; ++i
) {
349 if (strncmp(environment
->items
[i
].name
, kAuthorizationEnvironmentWindowId
, strlen(kAuthorizationEnvironmentWindowId
)) == 0
350 && (environment
->items
[i
].valueLength
= sizeof(window
)) && environment
->items
[i
].value
) {
351 window
= *(CGWindowID
*)environment
->items
[i
].value
;
356 os_log_debug(AUTH_LOG
, "Trying to use sheet version");
357 static OSStatus (*sheetAuthorizationWorker
)(CGWindowID windowID
, AuthorizationRef authorization
,
358 const AuthorizationRights
*rights
,
359 const AuthorizationEnvironment
*environment
,
360 AuthorizationFlags flags
,
361 AuthorizationRights
**authorizedRights
,
362 Boolean
*authorizationLaunched
) = NULL
;
363 static dispatch_once_t onceToken
;
364 dispatch_once(&onceToken
, ^{
365 void *handle
= dlopen("/System/Library/Frameworks/SecurityInterface.framework/SecurityInterface", RTLD_NOW
|RTLD_GLOBAL
|RTLD_NODELETE
);
367 sheetAuthorizationWorker
= dlsym(handle
, "sheetAuthorizationWorker");
371 if (sheetAuthorizationWorker
) {
372 Boolean authorizationLaunched
;
373 status
= sheetAuthorizationWorker(window
, authorization
, rights
, environment
, flags
, authorizedRights
, &authorizationLaunched
);
374 if (authorizationLaunched
== true) {
375 os_log_debug(AUTH_LOG
, "Returning sheet result %d", (int)status
);
378 os_log(AUTH_LOG
, "Sheet authorization cannot be used this time, falling back to the SecurityAgent UI");
380 os_log_debug(AUTH_LOG
, "Failed to find sheet support in SecurityInterface");
382 // fall back to the standard (windowed) version if sheets are not available
383 flags
&= ~kAuthorizationFlagSheet
;
387 xpc_object_t message
= NULL
;
389 require_noerr(status
= _AuthorizationCopyRights_prepare_message(authorization
, rights
, environment
, flags
, &message
), done
);
390 require_noerr(status
= _AuthorizationCopyRights_send_message(message
, authorizedRights
), done
);
393 xpc_release_safe(message
);
398 void AuthorizationCopyRightsAsync(AuthorizationRef authorization
,
399 const AuthorizationRights
*rights
,
400 const AuthorizationEnvironment
*environment
,
401 AuthorizationFlags flags
,
402 AuthorizationAsyncCallback callbackBlock
)
404 OSStatus prepare_status
= errAuthorizationInternal
;
405 __block xpc_object_t message
= NULL
;
407 prepare_status
= _AuthorizationCopyRights_prepare_message(authorization
, rights
, environment
, flags
, &message
);
408 if (prepare_status
!= errAuthorizationSuccess
) {
409 callbackBlock(prepare_status
, NULL
);
412 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^{
413 AuthorizationRights
*blockAuthorizedRights
= NULL
;
414 OSStatus status
= _AuthorizationCopyRights_send_message(message
, &blockAuthorizedRights
);
415 callbackBlock(status
, blockAuthorizedRights
);
416 xpc_release_safe(message
);
420 OSStatus
AuthorizationDismiss()
422 OSStatus status
= errAuthorizationInternal
;
423 xpc_object_t message
= NULL
;
424 xpc_object_t reply
= NULL
;
427 message
= xpc_dictionary_create(NULL
, NULL
, 0);
428 require(message
!= NULL
, done
);
430 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_DISMISS
);
433 xpc_connection_t conn
= get_authorization_connection();
434 require_action(conn
!= NULL
, done
, status
= errAuthorizationInternal
);
435 reply
= xpc_connection_send_message_with_reply_sync(conn
, message
);
436 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
437 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
440 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
443 xpc_release_safe(message
);
444 xpc_release_safe(reply
);
448 OSStatus
AuthorizationCopyInfo(AuthorizationRef authorization
,
449 AuthorizationString tag
,
450 AuthorizationItemSet
**info
)
452 OSStatus status
= errAuthorizationInternal
;
453 xpc_object_t message
= NULL
;
454 xpc_object_t reply
= NULL
;
455 AuthorizationBlob
*blob
= NULL
;
457 require_action(info
!= NULL
, done
, status
= errAuthorizationInvalidSet
);
458 require_action(authorization
!= NULL
, done
, status
= errAuthorizationInvalidRef
);
459 blob
= (AuthorizationBlob
*)authorization
;
462 message
= xpc_dictionary_create(NULL
, NULL
, 0);
463 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
465 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_COPY_INFO
);
466 xpc_dictionary_set_data(message
, AUTH_XPC_BLOB
, blob
, sizeof(AuthorizationBlob
));
468 xpc_dictionary_set_string(message
, AUTH_XPC_TAG
, tag
);
472 xpc_connection_t conn
= get_authorization_connection();
473 require_action(conn
!= NULL
, done
, status
= errAuthorizationInternal
);
474 reply
= xpc_connection_send_message_with_reply_sync(conn
, message
);
475 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
476 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
479 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
482 if (info
&& status
== errAuthorizationSuccess
) {
483 xpc_object_t tmpItems
= xpc_dictionary_get_value(reply
, AUTH_XPC_OUT_ITEMS
);
484 AuthorizationRights
* outInfo
= DeserializeItemSet(tmpItems
);
485 require_action(outInfo
!= NULL
, done
, status
= errAuthorizationInternal
);
491 xpc_release_safe(message
);
492 xpc_release_safe(reply
);
496 OSStatus
AuthorizationMakeExternalForm(AuthorizationRef authorization
,
497 AuthorizationExternalForm
*extForm
)
499 OSStatus status
= errAuthorizationInternal
;
500 xpc_object_t message
= NULL
;
501 xpc_object_t reply
= NULL
;
502 AuthorizationBlob
*blob
= NULL
;
504 require_action(extForm
!= NULL
, done
, status
= errAuthorizationInvalidPointer
);
505 require_action(authorization
!= NULL
, done
, status
= errAuthorizationInvalidRef
);
506 blob
= (AuthorizationBlob
*)authorization
;
509 message
= xpc_dictionary_create(NULL
, NULL
, 0);
510 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
512 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_MAKE_EXTERNAL_FORM
);
513 xpc_dictionary_set_data(message
, AUTH_XPC_BLOB
, blob
, sizeof(AuthorizationBlob
));
516 xpc_connection_t conn
= get_authorization_connection();
517 require_action(conn
!= NULL
, done
, status
= errAuthorizationInternal
);
518 reply
= xpc_connection_send_message_with_reply_sync(conn
, message
);
519 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
520 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
523 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
526 if (status
== errAuthorizationSuccess
) {
528 const void * data
= xpc_dictionary_get_data(reply
, AUTH_XPC_EXTERNAL
, &len
);
529 require_action(data
!= NULL
, done
, status
= errAuthorizationInternal
);
530 require_action(len
== sizeof(AuthorizationExternalForm
), done
, status
= errAuthorizationInternal
);
532 *extForm
= *(AuthorizationExternalForm
*)data
;
536 xpc_release_safe(message
);
537 xpc_release_safe(reply
);
541 OSStatus
AuthorizationCreateFromExternalForm(const AuthorizationExternalForm
*extForm
,
542 AuthorizationRef
*authorization
)
544 OSStatus status
= errAuthorizationInternal
;
545 xpc_object_t message
= NULL
;
546 xpc_object_t reply
= NULL
;
548 require_action(extForm
!= NULL
, done
, status
= errAuthorizationInvalidPointer
);
549 require_action(authorization
!= NULL
, done
, status
= errAuthorizationInvalidRef
);
552 message
= xpc_dictionary_create(NULL
, NULL
, 0);
553 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
555 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_CREATE_FROM_EXTERNAL_FORM
);
556 xpc_dictionary_set_data(message
, AUTH_XPC_EXTERNAL
, extForm
, sizeof(AuthorizationExternalForm
));
559 xpc_connection_t conn
= get_authorization_connection();
560 require_action(conn
!= NULL
, done
, status
= errAuthorizationInternal
);
561 reply
= xpc_connection_send_message_with_reply_sync(conn
, message
);
562 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
563 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
566 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
569 if (authorization
&& status
== errAuthorizationSuccess
) {
571 const void * data
= xpc_dictionary_get_data(reply
, AUTH_XPC_BLOB
, &len
);
572 require_action(data
!= NULL
, done
, status
= errAuthorizationInternal
);
573 require_action(len
== sizeof(AuthorizationBlob
), done
, status
= errAuthorizationInternal
);
575 AuthorizationBlob
* blob
= (AuthorizationBlob
*)calloc(1u, sizeof(AuthorizationBlob
));
576 require_action(blob
!= NULL
, done
, status
= errAuthorizationInternal
);
577 *blob
= *(AuthorizationBlob
*)data
;
579 *authorization
= (AuthorizationRef
)blob
;
583 xpc_release_safe(message
);
584 xpc_release_safe(reply
);
588 OSStatus
AuthorizationFreeItemSet(AuthorizationItemSet
*set
)
591 return errAuthorizationSuccess
;
594 OSStatus
AuthorizationEnableSmartCard(AuthorizationRef authRef
, Boolean enable
)
596 OSStatus status
= errAuthorizationInternal
;
597 xpc_object_t message
= NULL
;
598 xpc_object_t reply
= NULL
;
599 AuthorizationBlob
*blob
= NULL
;
602 message
= xpc_dictionary_create(NULL
, NULL
, 0);
603 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
604 require_action(authRef
!= NULL
, done
, status
= errAuthorizationInvalidRef
);
605 blob
= (AuthorizationBlob
*)authRef
;
606 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_ENABLE_SMARTCARD
);
607 xpc_dictionary_set_data(message
, AUTH_XPC_BLOB
, blob
, sizeof(AuthorizationBlob
));
608 xpc_dictionary_set_bool(message
, AUTH_XPC_DATA
, enable
);
611 xpc_connection_t conn
= get_authorization_connection();
612 require_action(conn
!= NULL
, done
, status
= errAuthorizationInternal
);
613 reply
= xpc_connection_send_message_with_reply_sync(conn
, 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 xpc_connection_t conn
= get_authorization_connection();
644 require_action(conn
!= NULL
, done
, status
= errAuthorizationInternal
);
645 reply
= xpc_connection_send_message_with_reply_sync(conn
, message
);
646 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
647 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
650 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
653 if (rightDefinition
&& status
== errAuthorizationSuccess
) {
654 xpc_object_t value
= xpc_dictionary_get_value(reply
, AUTH_XPC_DATA
);
655 require_action(value
!= NULL
, done
, status
= errAuthorizationInternal
);
656 require_action(xpc_get_type(value
) == XPC_TYPE_DICTIONARY
, done
, status
= errAuthorizationInternal
);
658 CFTypeRef cfdict
= _CFXPCCreateCFObjectFromXPCObject(value
);
659 require_action(cfdict
!= NULL
, done
, status
= errAuthorizationInternal
);
661 *rightDefinition
= cfdict
;
665 xpc_release_safe(message
);
666 xpc_release_safe(reply
);
670 OSStatus
AuthorizationRightSet(AuthorizationRef authRef
,
671 const char *rightName
,
672 CFTypeRef rightDefinition
,
673 CFStringRef descriptionKey
,
675 CFStringRef tableName
)
677 OSStatus status
= errAuthorizationInternal
;
678 xpc_object_t message
= NULL
;
679 xpc_object_t reply
= NULL
;
680 AuthorizationBlob
*blob
= NULL
;
681 CFMutableDictionaryRef rightDict
= NULL
;
682 CFBundleRef clientBundle
= bundle
;
688 require_action(rightDefinition
!= NULL
, done
, status
= errAuthorizationInvalidPointer
);
689 require_action(rightName
!= NULL
, done
, status
= errAuthorizationInvalidPointer
);
690 require_action(authRef
!= NULL
, done
, status
= errAuthorizationInvalidRef
);
691 blob
= (AuthorizationBlob
*)authRef
;
694 message
= xpc_dictionary_create(NULL
, NULL
, 0);
695 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
697 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_RIGHT_SET
);
698 xpc_dictionary_set_data(message
, AUTH_XPC_BLOB
, blob
, sizeof(AuthorizationBlob
));
699 xpc_dictionary_set_string(message
, AUTH_XPC_RIGHT_NAME
, rightName
);
702 if (CFGetTypeID(rightDefinition
) == CFStringGetTypeID()) {
703 rightDict
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
704 require_action(rightDict
!= NULL
, done
, status
= errAuthorizationInternal
);
706 CFDictionarySetValue(rightDict
, CFSTR(kAuthorizationRightRule
), rightDefinition
);
708 } else if (CFGetTypeID(rightDefinition
) == CFDictionaryGetTypeID()) {
709 rightDict
= CFDictionaryCreateMutableCopy(kCFAllocatorDefault
, 0, rightDefinition
);
710 require_action(rightDict
!= NULL
, done
, status
= errAuthorizationInternal
);
713 status
= errAuthorizationInvalidPointer
;
718 if (descriptionKey
) {
719 CFMutableDictionaryRef locDict
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
720 require_action(locDict
!= NULL
, done
, status
= errAuthorizationInternal
);
722 if (clientBundle
== NULL
) {
723 clientBundle
= CFBundleGetMainBundle();
724 CFRetain(clientBundle
);
728 CFArrayRef bundleLocalizations
= CFBundleCopyBundleLocalizations(clientBundle
);
729 if (bundleLocalizations
) {
730 // for every CFString in localizations do
731 CFIndex locIndex
, allLocs
= CFArrayGetCount(bundleLocalizations
);
732 for (locIndex
= 0; locIndex
< allLocs
; locIndex
++)
734 CFStringRef oneLocalization
= (CFStringRef
)CFArrayGetValueAtIndex(bundleLocalizations
, locIndex
);
736 if (!oneLocalization
)
739 // @@@ no way to get "Localized" and "strings" as constants?
740 CFURLRef locURL
= CFBundleCopyResourceURLForLocalization(clientBundle
, tableName
? tableName
: CFSTR("Localizable"), CFSTR("strings"), NULL
/*subDirName*/, oneLocalization
);
745 CFDataRef tableData
= NULL
;
747 CFStringRef errStr
= NULL
;
748 CFPropertyListRef stringTable
= NULL
;
750 CFURLCreateDataAndPropertiesFromResource(CFGetAllocator(clientBundle
), locURL
, &tableData
, NULL
, NULL
, &errCode
);
751 CFReleaseSafe(locURL
);
754 CFReleaseSafe(tableData
);
758 stringTable
= CFPropertyListCreateFromXMLData(CFGetAllocator(clientBundle
), tableData
, kCFPropertyListImmutable
, &errStr
);
759 CFReleaseSafe(errStr
);
760 CFReleaseSafe(tableData
);
762 CFStringRef value
= (CFStringRef
)CFDictionaryGetValue(stringTable
, descriptionKey
);
763 if (value
== NULL
|| CFEqual(value
, CFSTR(""))) {
764 CFReleaseSafe(stringTable
);
767 // oneLocalization/value into our dictionary
768 CFDictionarySetValue(locDict
, oneLocalization
, value
);
769 CFReleaseSafe(stringTable
);
772 CFReleaseSafe(bundleLocalizations
);
776 // add the description as the default localization into the dictionary
777 CFDictionarySetValue(locDict
, CFSTR(""), descriptionKey
);
779 // stuff localization table into right definition
780 CFDictionarySetValue(rightDict
, CFSTR(kAuthorizationRuleParameterDefaultPrompt
), locDict
);
781 CFReleaseSafe(locDict
);
784 xpc_object_t value
= _CFXPCCreateXPCObjectFromCFObject(rightDict
);
785 xpc_dictionary_set_value(message
, AUTH_XPC_DATA
, value
);
786 xpc_release_safe(value
);
789 xpc_connection_t conn
= get_authorization_connection();
790 require_action(conn
!= NULL
, done
, status
= errAuthorizationInternal
);
791 reply
= xpc_connection_send_message_with_reply_sync(conn
, message
);
792 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
793 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
796 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
799 CFReleaseSafe(clientBundle
);
800 CFReleaseSafe(rightDict
);
801 xpc_release_safe(message
);
802 xpc_release_safe(reply
);
806 OSStatus
AuthorizationRightRemove(AuthorizationRef authorization
,
807 const char *rightName
)
809 OSStatus status
= errAuthorizationInternal
;
810 xpc_object_t message
= NULL
;
811 xpc_object_t reply
= NULL
;
812 AuthorizationBlob
*blob
= NULL
;
814 require_action(rightName
!= NULL
, done
, status
= errAuthorizationInvalidPointer
);
815 require_action(authorization
!= NULL
, done
, status
= errAuthorizationInvalidRef
);
816 blob
= (AuthorizationBlob
*)authorization
;
819 message
= xpc_dictionary_create(NULL
, NULL
, 0);
820 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
822 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_RIGHT_REMOVE
);
823 xpc_dictionary_set_data(message
, AUTH_XPC_BLOB
, blob
, sizeof(AuthorizationBlob
));
824 xpc_dictionary_set_string(message
, AUTH_XPC_RIGHT_NAME
, rightName
);
827 xpc_connection_t conn
= get_authorization_connection();
828 require_action(conn
!= NULL
, done
, status
= errAuthorizationInternal
);
829 reply
= xpc_connection_send_message_with_reply_sync(conn
, message
);
830 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
831 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
834 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
837 xpc_release_safe(message
);
838 xpc_release_safe(reply
);
842 OSStatus
AuthorizationCopyPreloginUserDatabase(const char * _Nullable
const volumeUuid
, const UInt32 flags
, CFArrayRef _Nonnull
* _Nonnull output
)
844 OSStatus status
= errAuthorizationInternal
;
845 xpc_object_t message
= NULL
;
846 xpc_object_t reply
= NULL
;
848 require_action(output
!= NULL
, done
, status
= errAuthorizationInvalidRef
);
851 message
= xpc_dictionary_create(NULL
, NULL
, 0);
852 require_action(message
!= NULL
, done
, status
= errAuthorizationInternal
);
853 xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_COPY_PRELOGIN_USERDB
);
855 xpc_dictionary_set_string(message
, AUTH_XPC_TAG
, volumeUuid
);
857 xpc_dictionary_set_uint64(message
, AUTH_XPC_FLAGS
, flags
);
860 xpc_connection_t conn
= get_authorization_connection();
861 require_action(conn
!= NULL
, done
, status
= errAuthorizationInternal
);
862 reply
= xpc_connection_send_message_with_reply_sync(conn
, message
);
863 require_action(reply
!= NULL
, done
, status
= errAuthorizationInternal
);
864 require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status
= errAuthorizationInternal
);
866 status
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
);
869 if (status
== errAuthorizationSuccess
) {
870 *output
= _CFXPCCreateCFObjectFromXPCObject(xpc_dictionary_get_value(reply
, AUTH_XPC_DATA
));
874 xpc_release_safe(message
);
875 xpc_release_safe(reply
);