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 
 386     xpc_object_t message 
= NULL
; 
 388     require_noerr(status 
= _AuthorizationCopyRights_prepare_message(authorization
, rights
, environment
, flags
, &message
), done
); 
 389     require_noerr(status 
= _AuthorizationCopyRights_send_message(message
, authorizedRights
), done
); 
 392     xpc_release_safe(message
); 
 397 void AuthorizationCopyRightsAsync(AuthorizationRef authorization
, 
 398                          const AuthorizationRights 
*rights
, 
 399                          const AuthorizationEnvironment 
*environment
, 
 400                          AuthorizationFlags flags
, 
 401                          AuthorizationAsyncCallback callbackBlock
) 
 403     OSStatus prepare_status 
= errAuthorizationInternal
; 
 404     __block xpc_object_t message 
= NULL
; 
 406     prepare_status 
= _AuthorizationCopyRights_prepare_message(authorization
, rights
, environment
, flags
, &message
); 
 407     if (prepare_status 
!= errAuthorizationSuccess
) { 
 408         callbackBlock(prepare_status
, NULL
); 
 411     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^{ 
 412                 AuthorizationRights 
*blockAuthorizedRights 
= NULL
; 
 413         OSStatus status 
= _AuthorizationCopyRights_send_message(message
, &blockAuthorizedRights
); 
 414         callbackBlock(status
, blockAuthorizedRights
); 
 415         xpc_release_safe(message
); 
 419 OSStatus 
AuthorizationDismiss() 
 421     OSStatus status 
= errAuthorizationInternal
; 
 422     xpc_object_t message 
= NULL
; 
 423     xpc_object_t reply 
= NULL
; 
 426     message 
= xpc_dictionary_create(NULL
, NULL
, 0); 
 427     require(message 
!= NULL
, done
); 
 429     xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_DISMISS
); 
 432     xpc_connection_t conn 
= get_authorization_connection(); 
 433     require_action(conn 
!= NULL
, done
, status 
= errAuthorizationInternal
); 
 434     reply 
= xpc_connection_send_message_with_reply_sync(conn
, message
); 
 435     require_action(reply 
!= NULL
, done
, status 
= errAuthorizationInternal
); 
 436     require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status 
= errAuthorizationInternal
); 
 439     status 
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
); 
 442     xpc_release_safe(message
); 
 443     xpc_release_safe(reply
); 
 447 OSStatus 
AuthorizationCopyInfo(AuthorizationRef authorization
, 
 448                       AuthorizationString tag
, 
 449                       AuthorizationItemSet 
**info
) 
 451     OSStatus status 
= errAuthorizationInternal
; 
 452     xpc_object_t message 
= NULL
; 
 453     xpc_object_t reply 
= NULL
; 
 454     AuthorizationBlob 
*blob 
= NULL
; 
 456     require_action(info 
!= NULL
, done
, status 
= errAuthorizationInvalidSet
); 
 457     require_action(authorization 
!= NULL
, done
, status 
= errAuthorizationInvalidRef
); 
 458     blob 
= (AuthorizationBlob 
*)authorization
; 
 461     message 
= xpc_dictionary_create(NULL
, NULL
, 0); 
 462     require_action(message 
!= NULL
, done
, status 
= errAuthorizationInternal
); 
 464     xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_COPY_INFO
); 
 465     xpc_dictionary_set_data(message
, AUTH_XPC_BLOB
, blob
, sizeof(AuthorizationBlob
)); 
 467         xpc_dictionary_set_string(message
, AUTH_XPC_TAG
, tag
); 
 471     xpc_connection_t conn 
= get_authorization_connection(); 
 472     require_action(conn 
!= NULL
, done
, status 
= errAuthorizationInternal
); 
 473     reply 
= xpc_connection_send_message_with_reply_sync(conn
, message
); 
 474     require_action(reply 
!= NULL
, done
, status 
= errAuthorizationInternal
); 
 475     require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status 
= errAuthorizationInternal
); 
 478     status 
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
); 
 481     if (info 
&& status 
== errAuthorizationSuccess
) { 
 482         xpc_object_t tmpItems 
= xpc_dictionary_get_value(reply
, AUTH_XPC_OUT_ITEMS
); 
 483         AuthorizationRights 
* outInfo 
= DeserializeItemSet(tmpItems
); 
 484         require_action(outInfo 
!= NULL
, done
, status 
= errAuthorizationInternal
); 
 490     xpc_release_safe(message
); 
 491     xpc_release_safe(reply
); 
 495 OSStatus 
AuthorizationMakeExternalForm(AuthorizationRef authorization
, 
 496                               AuthorizationExternalForm 
*extForm
) 
 498     OSStatus status 
= errAuthorizationInternal
; 
 499     xpc_object_t message 
= NULL
; 
 500     xpc_object_t reply 
= NULL
; 
 501     AuthorizationBlob 
*blob 
= NULL
; 
 503     require_action(extForm 
!= NULL
, done
, status 
= errAuthorizationInvalidPointer
); 
 504     require_action(authorization 
!= NULL
, done
, status 
= errAuthorizationInvalidRef
); 
 505     blob 
= (AuthorizationBlob 
*)authorization
; 
 508     message 
= xpc_dictionary_create(NULL
, NULL
, 0); 
 509     require_action(message 
!= NULL
, done
, status 
= errAuthorizationInternal
); 
 511     xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_MAKE_EXTERNAL_FORM
); 
 512     xpc_dictionary_set_data(message
, AUTH_XPC_BLOB
, blob
, sizeof(AuthorizationBlob
)); 
 515     xpc_connection_t conn 
= get_authorization_connection(); 
 516     require_action(conn 
!= NULL
, done
, status 
= errAuthorizationInternal
); 
 517     reply 
= xpc_connection_send_message_with_reply_sync(conn
, message
); 
 518     require_action(reply 
!= NULL
, done
, status 
= errAuthorizationInternal
); 
 519     require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status 
= errAuthorizationInternal
); 
 522     status 
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
); 
 525     if (status 
== errAuthorizationSuccess
) { 
 527         const void * data 
= xpc_dictionary_get_data(reply
, AUTH_XPC_EXTERNAL
, &len
); 
 528         require_action(data 
!= NULL
, done
, status 
= errAuthorizationInternal
); 
 529         require_action(len 
== sizeof(AuthorizationExternalForm
), done
, status 
= errAuthorizationInternal
); 
 531         *extForm 
= *(AuthorizationExternalForm
*)data
; 
 535     xpc_release_safe(message
); 
 536     xpc_release_safe(reply
); 
 540 OSStatus 
AuthorizationCreateFromExternalForm(const AuthorizationExternalForm 
*extForm
, 
 541                                     AuthorizationRef 
*authorization
) 
 543     OSStatus status 
= errAuthorizationInternal
; 
 544     xpc_object_t message 
= NULL
; 
 545     xpc_object_t reply 
= NULL
; 
 547     require_action(extForm 
!= NULL
, done
, status 
= errAuthorizationInvalidPointer
); 
 548     require_action(authorization 
!= NULL
, done
, status 
= errAuthorizationInvalidRef
); 
 551     message 
= xpc_dictionary_create(NULL
, NULL
, 0); 
 552     require_action(message 
!= NULL
, done
, status 
= errAuthorizationInternal
); 
 554     xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_CREATE_FROM_EXTERNAL_FORM
); 
 555     xpc_dictionary_set_data(message
, AUTH_XPC_EXTERNAL
, extForm
, sizeof(AuthorizationExternalForm
)); 
 558     xpc_connection_t conn 
= get_authorization_connection(); 
 559     require_action(conn 
!= NULL
, done
, status 
= errAuthorizationInternal
); 
 560     reply 
= xpc_connection_send_message_with_reply_sync(conn
, message
); 
 561     require_action(reply 
!= NULL
, done
, status 
= errAuthorizationInternal
); 
 562     require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status 
= errAuthorizationInternal
); 
 565     status 
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
); 
 568     if (authorization 
&& status 
== errAuthorizationSuccess
) { 
 570         const void * data 
= xpc_dictionary_get_data(reply
, AUTH_XPC_BLOB
, &len
); 
 571         require_action(data 
!= NULL
, done
, status 
= errAuthorizationInternal
); 
 572         require_action(len 
== sizeof(AuthorizationBlob
), done
, status 
= errAuthorizationInternal
); 
 574         AuthorizationBlob 
* blob 
= (AuthorizationBlob
*)calloc(1u, sizeof(AuthorizationBlob
)); 
 575         require_action(blob 
!= NULL
, done
, status 
= errAuthorizationInternal
); 
 576         *blob 
= *(AuthorizationBlob
*)data
; 
 578         *authorization 
= (AuthorizationRef
)blob
; 
 582     xpc_release_safe(message
); 
 583     xpc_release_safe(reply
); 
 587 OSStatus 
AuthorizationFreeItemSet(AuthorizationItemSet 
*set
) 
 590     return errAuthorizationSuccess
; 
 593 OSStatus 
AuthorizationEnableSmartCard(AuthorizationRef authRef
, Boolean enable
) 
 595     OSStatus status 
= errAuthorizationInternal
; 
 596     xpc_object_t message 
= NULL
; 
 597     xpc_object_t reply 
= NULL
; 
 598     AuthorizationBlob 
*blob 
= NULL
; 
 601     message 
= xpc_dictionary_create(NULL
, NULL
, 0); 
 602     require_action(message 
!= NULL
, done
, status 
= errAuthorizationInternal
); 
 603     require_action(authRef 
!= NULL
, done
, status 
= errAuthorizationInvalidRef
); 
 604     blob 
= (AuthorizationBlob 
*)authRef
; 
 605     xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_ENABLE_SMARTCARD
); 
 606     xpc_dictionary_set_data(message
, AUTH_XPC_BLOB
, blob
, sizeof(AuthorizationBlob
)); 
 607     xpc_dictionary_set_bool(message
, AUTH_XPC_DATA
, enable
); 
 610     xpc_connection_t conn 
= get_authorization_connection(); 
 611     require_action(conn 
!= NULL
, done
, status 
= errAuthorizationInternal
); 
 612     reply 
= xpc_connection_send_message_with_reply_sync(conn
, message
); 
 613     require_action(reply 
!= NULL
, done
, status 
= errAuthorizationInternal
); 
 614     require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status 
= errAuthorizationInternal
); 
 616     status 
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
); 
 619     xpc_release_safe(message
); 
 620     xpc_release_safe(reply
); 
 625 OSStatus 
AuthorizationRightGet(const char *rightName
, 
 626                       CFDictionaryRef 
*rightDefinition
) 
 628     OSStatus status 
= errAuthorizationInternal
; 
 629     xpc_object_t message 
= NULL
; 
 630     xpc_object_t reply 
= NULL
; 
 632     require_action(rightName 
!= NULL
, done
, status 
= errAuthorizationInvalidPointer
); 
 635     message 
= xpc_dictionary_create(NULL
, NULL
, 0); 
 636     require_action(message 
!= NULL
, done
, status 
= errAuthorizationInternal
); 
 638     xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_RIGHT_GET
); 
 639     xpc_dictionary_set_string(message
, AUTH_XPC_RIGHT_NAME
, rightName
); 
 642     xpc_connection_t conn 
= get_authorization_connection(); 
 643     require_action(conn 
!= NULL
, done
, status 
= errAuthorizationInternal
); 
 644     reply 
= xpc_connection_send_message_with_reply_sync(conn
, message
); 
 645     require_action(reply 
!= NULL
, done
, status 
= errAuthorizationInternal
); 
 646     require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status 
= errAuthorizationInternal
); 
 649     status 
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
); 
 652     if (rightDefinition 
&& status 
== errAuthorizationSuccess
) { 
 653         xpc_object_t value 
= xpc_dictionary_get_value(reply
, AUTH_XPC_DATA
); 
 654         require_action(value 
!= NULL
, done
, status 
= errAuthorizationInternal
); 
 655         require_action(xpc_get_type(value
) == XPC_TYPE_DICTIONARY
, done
, status 
= errAuthorizationInternal
); 
 657         CFTypeRef cfdict 
= _CFXPCCreateCFObjectFromXPCObject(value
); 
 658         require_action(cfdict 
!= NULL
, done
, status 
= errAuthorizationInternal
); 
 660         *rightDefinition 
= cfdict
; 
 664     xpc_release_safe(message
); 
 665     xpc_release_safe(reply
); 
 669 OSStatus 
AuthorizationRightSet(AuthorizationRef authRef
, 
 670                       const char *rightName
, 
 671                       CFTypeRef rightDefinition
, 
 672                       CFStringRef descriptionKey
, 
 674                       CFStringRef tableName
) 
 676     OSStatus status 
= errAuthorizationInternal
; 
 677     xpc_object_t message 
= NULL
; 
 678     xpc_object_t reply 
= NULL
; 
 679     AuthorizationBlob 
*blob 
= NULL
; 
 680     CFMutableDictionaryRef rightDict 
= NULL
; 
 681     CFBundleRef clientBundle 
= bundle
; 
 687     require_action(rightDefinition 
!= NULL
, done
, status 
= errAuthorizationInvalidPointer
); 
 688     require_action(rightName 
!= NULL
, done
, status 
= errAuthorizationInvalidPointer
); 
 689     require_action(authRef 
!= NULL
, done
, status 
= errAuthorizationInvalidRef
); 
 690     blob 
= (AuthorizationBlob 
*)authRef
; 
 693     message 
= xpc_dictionary_create(NULL
, NULL
, 0); 
 694     require_action(message 
!= NULL
, done
, status 
= errAuthorizationInternal
); 
 696     xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_RIGHT_SET
); 
 697     xpc_dictionary_set_data(message
, AUTH_XPC_BLOB
, blob
, sizeof(AuthorizationBlob
)); 
 698     xpc_dictionary_set_string(message
, AUTH_XPC_RIGHT_NAME
, rightName
); 
 701     if (CFGetTypeID(rightDefinition
) == CFStringGetTypeID()) { 
 702         rightDict 
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
); 
 703         require_action(rightDict 
!= NULL
, done
, status 
= errAuthorizationInternal
); 
 705         CFDictionarySetValue(rightDict
, CFSTR(kAuthorizationRightRule
), rightDefinition
); 
 707     } else if (CFGetTypeID(rightDefinition
) == CFDictionaryGetTypeID()) { 
 708         rightDict 
= CFDictionaryCreateMutableCopy(kCFAllocatorDefault
, 0, rightDefinition
); 
 709         require_action(rightDict 
!= NULL
, done
, status 
= errAuthorizationInternal
); 
 712         status 
= errAuthorizationInvalidPointer
; 
 717     if (descriptionKey
) { 
 718         CFMutableDictionaryRef locDict 
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
); 
 719         require_action(locDict 
!= NULL
, done
, status 
= errAuthorizationInternal
); 
 721         if (clientBundle 
== NULL
) { 
 722             clientBundle 
= CFBundleGetMainBundle(); 
 723             CFRetain(clientBundle
); 
 727             CFArrayRef bundleLocalizations 
= CFBundleCopyBundleLocalizations(clientBundle
); 
 728             if (bundleLocalizations
) { 
 729                 // for every CFString in localizations do 
 730                 CFIndex locIndex
, allLocs 
= CFArrayGetCount(bundleLocalizations
); 
 731                 for (locIndex 
= 0; locIndex 
< allLocs
; locIndex
++) 
 733                     CFStringRef oneLocalization 
= (CFStringRef
)CFArrayGetValueAtIndex(bundleLocalizations
, locIndex
); 
 735                     if (!oneLocalization
) 
 738                     // @@@ no way to get "Localized" and "strings" as constants? 
 739                     CFURLRef locURL 
= CFBundleCopyResourceURLForLocalization(clientBundle
, tableName 
? tableName 
:  CFSTR("Localizable"), CFSTR("strings"), NULL 
/*subDirName*/, oneLocalization
); 
 744                     CFDataRef tableData 
= NULL
; 
 746                     CFStringRef errStr 
= NULL
; 
 747                     CFPropertyListRef stringTable 
= NULL
; 
 749                     CFURLCreateDataAndPropertiesFromResource(CFGetAllocator(clientBundle
), locURL
, &tableData
, NULL
, NULL
, &errCode
); 
 750                     CFReleaseSafe(locURL
); 
 753                         CFReleaseSafe(tableData
); 
 757                     stringTable 
= CFPropertyListCreateFromXMLData(CFGetAllocator(clientBundle
), tableData
, kCFPropertyListImmutable
, &errStr
); 
 758                     CFReleaseSafe(errStr
); 
 759                     CFReleaseSafe(tableData
); 
 761                     CFStringRef value 
= (CFStringRef
)CFDictionaryGetValue(stringTable
, descriptionKey
); 
 762                     if (value 
== NULL 
|| CFEqual(value
, CFSTR(""))) { 
 763                         CFReleaseSafe(stringTable
); 
 766                         // oneLocalization/value into our dictionary  
 767                         CFDictionarySetValue(locDict
, oneLocalization
, value
); 
 768                         CFReleaseSafe(stringTable
); 
 771                 CFReleaseSafe(bundleLocalizations
); 
 775         // add the description as the default localization into the dictionary 
 776                 CFDictionarySetValue(locDict
, CFSTR(""), descriptionKey
); 
 778                 // stuff localization table into right definition 
 779                 CFDictionarySetValue(rightDict
, CFSTR(kAuthorizationRuleParameterDefaultPrompt
), locDict
); 
 780         CFReleaseSafe(locDict
); 
 783     xpc_object_t value 
= _CFXPCCreateXPCObjectFromCFObject(rightDict
); 
 784     xpc_dictionary_set_value(message
, AUTH_XPC_DATA
, value
); 
 785     xpc_release_safe(value
); 
 788     xpc_connection_t conn 
= get_authorization_connection(); 
 789     require_action(conn 
!= NULL
, done
, status 
= errAuthorizationInternal
); 
 790     reply 
= xpc_connection_send_message_with_reply_sync(conn
, message
); 
 791     require_action(reply 
!= NULL
, done
, status 
= errAuthorizationInternal
); 
 792     require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status 
= errAuthorizationInternal
); 
 795     status 
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
); 
 798     CFReleaseSafe(clientBundle
); 
 799     CFReleaseSafe(rightDict
); 
 800     xpc_release_safe(message
); 
 801     xpc_release_safe(reply
); 
 805 OSStatus 
AuthorizationRightRemove(AuthorizationRef authorization
, 
 806                          const char *rightName
) 
 808     OSStatus status 
= errAuthorizationInternal
; 
 809     xpc_object_t message 
= NULL
; 
 810     xpc_object_t reply 
= NULL
; 
 811     AuthorizationBlob 
*blob 
= NULL
; 
 813     require_action(rightName 
!= NULL
, done
, status 
= errAuthorizationInvalidPointer
); 
 814     require_action(authorization 
!= NULL
, done
, status 
= errAuthorizationInvalidRef
); 
 815     blob 
= (AuthorizationBlob 
*)authorization
; 
 818     message 
= xpc_dictionary_create(NULL
, NULL
, 0); 
 819     require_action(message 
!= NULL
, done
, status 
= errAuthorizationInternal
); 
 821     xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_RIGHT_REMOVE
); 
 822     xpc_dictionary_set_data(message
, AUTH_XPC_BLOB
, blob
, sizeof(AuthorizationBlob
)); 
 823     xpc_dictionary_set_string(message
, AUTH_XPC_RIGHT_NAME
, rightName
); 
 826     xpc_connection_t conn 
= get_authorization_connection(); 
 827     require_action(conn 
!= NULL
, done
, status 
= errAuthorizationInternal
); 
 828     reply 
= xpc_connection_send_message_with_reply_sync(conn
, message
); 
 829     require_action(reply 
!= NULL
, done
, status 
= errAuthorizationInternal
); 
 830     require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status 
= errAuthorizationInternal
); 
 833     status 
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
); 
 836     xpc_release_safe(message
); 
 837     xpc_release_safe(reply
); 
 841 OSStatus 
AuthorizationCopyPreloginUserDatabase(const char * _Nullable 
const volumeUuid
, const UInt32 flags
, CFArrayRef _Nonnull 
* _Nonnull output
) 
 843     OSStatus status 
= errAuthorizationInternal
; 
 844     xpc_object_t message 
= NULL
; 
 845     xpc_object_t reply 
= NULL
; 
 847     require_action(output 
!= NULL
, done
, status 
= errAuthorizationInvalidRef
); 
 850     message 
= xpc_dictionary_create(NULL
, NULL
, 0); 
 851     require_action(message 
!= NULL
, done
, status 
= errAuthorizationInternal
); 
 852     xpc_dictionary_set_uint64(message
, AUTH_XPC_TYPE
, AUTHORIZATION_COPY_PRELOGIN_USERDB
); 
 854         xpc_dictionary_set_string(message
, AUTH_XPC_TAG
, volumeUuid
); 
 856     xpc_dictionary_set_uint64(message
, AUTH_XPC_FLAGS
, flags
); 
 859     xpc_connection_t conn 
= get_authorization_connection(); 
 860     require_action(conn 
!= NULL
, done
, status 
= errAuthorizationInternal
); 
 861     reply 
= xpc_connection_send_message_with_reply_sync(conn
, message
); 
 862     require_action(reply 
!= NULL
, done
, status 
= errAuthorizationInternal
); 
 863     require_action(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
, status 
= errAuthorizationInternal
); 
 865     status 
= (OSStatus
)xpc_dictionary_get_int64(reply
, AUTH_XPC_STATUS
); 
 868     if (status 
== errAuthorizationSuccess
) { 
 869         *output 
= _CFXPCCreateCFObjectFromXPCObject(xpc_dictionary_get_value(reply
, AUTH_XPC_DATA
)); 
 873     xpc_release_safe(message
); 
 874     xpc_release_safe(reply
);