1/* Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */ 2 3#include "Authorization.h" 4#include "authd_private.h" 5#include "authutilities.h" 6#include "debugging.h" 7 8#include <Security/AuthorizationPriv.h> 9#include <Security/AuthorizationDB.h> 10#include <Security/AuthorizationTags.h> 11#include <Security/AuthorizationTagsPriv.h> 12#include <xpc/xpc.h> 13#include <xpc/private.h> 14#include <mach/mach.h> 15#include <syslog.h> 16#include <AssertMacros.h> 17#include <CoreFoundation/CFXPCBridge.h> 18 19static dispatch_queue_t 20get_authorization_dispatch_queue() 21{ 22 static dispatch_once_t onceToken = 0; 23 static dispatch_queue_t connection_queue = NULL; 24 25 dispatch_once(&onceToken, ^{ 26 connection_queue = dispatch_queue_create("authorization-connection-queue", DISPATCH_QUEUE_SERIAL); 27 }); 28 29 return connection_queue; 30} 31 32static xpc_connection_t 33get_authorization_connection() 34{ 35 static xpc_connection_t connection = NULL; 36 37 dispatch_sync(get_authorization_dispatch_queue(), ^{ 38 if (connection == NULL) { 39 connection = xpc_connection_create(SECURITY_AUTH_NAME, NULL); 40 41 if (!connection) { 42 syslog(LOG_ERR, "Authorization, failed to create xpc connection to %s", SECURITY_AUTH_NAME); 43 connection = xpc_connection_create(SECURITY_AUTH_NAME, NULL); 44 } 45 46 xpc_connection_set_event_handler(connection, ^(xpc_object_t event) { 47 if (xpc_get_type(event) == XPC_TYPE_ERROR) { 48 if (event == XPC_ERROR_CONNECTION_INVALID) { 49 syslog(LOG_ERR, "Authorization, server not available"); 50 } 51 // XPC_ERROR_CONNECTION_INTERRUPTED 52 // XPC_ERROR_TERMINATION_IMMINENT 53 } else { 54 char * desc = xpc_copy_description(event); 55 syslog(LOG_ERR, "Authorization, we should never get messages on this connection: %s", desc); 56 free(desc); 57 } 58 }); 59 60 xpc_connection_resume(connection); 61 62 // Send 63 xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0); 64 xpc_dictionary_set_uint64(message, AUTH_XPC_TYPE, AUTHORIZATION_SETUP); 65 mach_port_t bootstrap = MACH_PORT_NULL; 66 task_get_bootstrap_port(mach_task_self(), &bootstrap); 67 xpc_dictionary_set_mach_send(message, AUTH_XPC_BOOTSTRAP, bootstrap); 68 xpc_object_t reply = xpc_connection_send_message_with_reply_sync(connection, message); 69 xpc_release_safe(message); 70 xpc_release_safe(reply); 71 } 72 }); 73 74 return connection; 75} 76 77static void 78setItemSet(xpc_object_t message, const char * key, const AuthorizationItemSet * itemSet) 79{ 80 xpc_object_t serialized = SerializeItemSet(itemSet); 81 if (serialized) { 82 xpc_dictionary_set_value(message, key, serialized); 83 xpc_release(serialized); 84 } 85} 86 87OSStatus AuthorizationCreate(const AuthorizationRights *rights, 88 const AuthorizationEnvironment *environment, 89 AuthorizationFlags flags, 90 AuthorizationRef *authorization) 91{ 92 OSStatus status = errAuthorizationInternal; 93 xpc_object_t message = NULL; 94 xpc_object_t reply = NULL; 95 96// require_action(!(rights == NULL && authorization == NULL), done, status = errAuthorizationInvalidSet); 97 98 // Send 99 message = xpc_dictionary_create(NULL, NULL, 0); 100 require_action(message != NULL, done, status = errAuthorizationInternal); 101 102 xpc_dictionary_set_uint64(message, AUTH_XPC_TYPE, AUTHORIZATION_CREATE); 103 setItemSet(message, AUTH_XPC_RIGHTS, rights); 104 setItemSet(message, AUTH_XPC_ENVIROMENT, environment); 105 xpc_dictionary_set_uint64(message, AUTH_XPC_FLAGS, flags | (authorization ? 0 : kAuthorizationFlagNoData)); 106 107 // Reply 108 reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); 109 require_action(reply != NULL, done, status = errAuthorizationInternal); 110 require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); 111 112 // Status 113 status = (OSStatus)xpc_dictionary_get_int64(reply, AUTH_XPC_STATUS); 114 115 // Out 116 if (authorization && status == errAuthorizationSuccess) { 117 size_t len; 118 const void * data = xpc_dictionary_get_data(reply, AUTH_XPC_BLOB, &len); 119 require_action(data != NULL, done, status = errAuthorizationInternal); 120 assert(len == sizeof(AuthorizationBlob)); 121 122 AuthorizationBlob * blob = (AuthorizationBlob*)calloc(1u, sizeof(AuthorizationBlob)); 123 require_action(blob != NULL, done, status = errAuthorizationInternal); 124 *blob = *(AuthorizationBlob*)data; 125 126 *authorization = (AuthorizationRef)blob; 127 } 128 129done: 130 xpc_release_safe(message); 131 xpc_release_safe(reply); 132 return status; 133} 134 135OSStatus AuthorizationCreateWithAuditToken(audit_token_t token, 136 const AuthorizationEnvironment *environment, 137 AuthorizationFlags flags, 138 AuthorizationRef *authorization) 139{ 140 OSStatus status = errAuthorizationInternal; 141 xpc_object_t message = NULL; 142 xpc_object_t reply = NULL; 143 144 require_action(authorization != NULL, done, status = errAuthorizationInvalidPointer); 145 146 // Send 147 message = xpc_dictionary_create(NULL, NULL, 0); 148 require_action(message != NULL, done, status = errAuthorizationInternal); 149 150 xpc_dictionary_set_uint64(message, AUTH_XPC_TYPE, AUTHORIZATION_CREATE_WITH_AUDIT_TOKEN); 151 xpc_dictionary_set_data(message, AUTH_XPC_DATA, &token, sizeof(token)); 152 setItemSet(message, AUTH_XPC_ENVIROMENT, environment); 153 xpc_dictionary_set_uint64(message, AUTH_XPC_FLAGS, flags); 154 155 // Reply 156 reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); 157 require_action(reply != NULL, done, status = errAuthorizationInternal); 158 require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); 159 160 // Status 161 status = (OSStatus)xpc_dictionary_get_int64(reply, AUTH_XPC_STATUS); 162 163 // Out 164 if (status == errAuthorizationSuccess) { 165 size_t len; 166 const void * data = xpc_dictionary_get_data(reply, AUTH_XPC_BLOB, &len); 167 require_action(data != NULL, done, status = errAuthorizationInternal); 168 assert(len == sizeof(AuthorizationBlob)); 169 170 AuthorizationBlob * blob = (AuthorizationBlob*)calloc(1u, sizeof(AuthorizationBlob)); 171 require_action(blob != NULL, done, status = errAuthorizationInternal); 172 *blob = *(AuthorizationBlob*)data; 173 174 *authorization = (AuthorizationRef)blob; 175 } 176 177done: 178 xpc_release_safe(message); 179 xpc_release_safe(reply); 180 return status; 181} 182 183OSStatus AuthorizationFree(AuthorizationRef authorization, AuthorizationFlags flags) 184{ 185 OSStatus status = errAuthorizationInternal; 186 xpc_object_t message = NULL; 187 xpc_object_t reply = NULL; 188 AuthorizationBlob *blob = NULL; 189 190 require_action(authorization != NULL, done, status = errAuthorizationInvalidRef); 191 blob = (AuthorizationBlob *)authorization; 192 193 // Send 194 message = xpc_dictionary_create(NULL, NULL, 0); 195 require_action(message != NULL, done, status = errAuthorizationInternal); 196 197 xpc_dictionary_set_uint64(message, AUTH_XPC_TYPE, AUTHORIZATION_FREE); 198 xpc_dictionary_set_data(message, AUTH_XPC_BLOB, blob, sizeof(AuthorizationBlob)); 199 xpc_dictionary_set_uint64(message, AUTH_XPC_FLAGS, flags); 200 201 // Reply 202 reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); 203 require_action(reply != NULL, done, status = errAuthorizationInternal); 204 require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); 205 206 // Status 207 status = (OSStatus)xpc_dictionary_get_int64(reply, AUTH_XPC_STATUS); 208 209 // Free 210 free(blob); 211 212done: 213 xpc_release_safe(message); 214 xpc_release_safe(reply); 215 return status; 216} 217 218static OSStatus 219_AuthorizationCopyRights_send_message(xpc_object_t message, AuthorizationRights **authorizedRights) 220{ 221 OSStatus status = errAuthorizationInternal; 222 xpc_object_t reply = NULL; 223 224 // Send 225 require_action(message != NULL, done, status = errAuthorizationInternal); 226 227 // Reply 228 reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); 229 require_action(reply != NULL, done, status = errAuthorizationInternal); 230 require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); 231 232 // Status 233 status = (OSStatus)xpc_dictionary_get_int64(reply, AUTH_XPC_STATUS); 234 235 // Out 236 if (authorizedRights && status == errAuthorizationSuccess) { 237 xpc_object_t tmpItems = xpc_dictionary_get_value(reply, AUTH_XPC_OUT_ITEMS); 238 AuthorizationRights * grantedRights = DeserializeItemSet(tmpItems); 239 require_action(grantedRights != NULL, done, status = errAuthorizationInternal); 240 241 *authorizedRights = grantedRights; 242 } 243 244done: 245 xpc_release_safe(reply); 246 return status; 247} 248 249static OSStatus 250_AuthorizationCopyRights_prepare_message(AuthorizationRef authorization, const AuthorizationRights *rights, const AuthorizationEnvironment *environment, AuthorizationFlags flags, xpc_object_t *message_out) 251{ 252 OSStatus status = errAuthorizationInternal; 253 AuthorizationBlob *blob = NULL; 254 xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0); 255 require_action(message != NULL, done, status = errAuthorizationInternal); 256 257 require_action(authorization != NULL, done, status = errAuthorizationInvalidRef); 258 blob = (AuthorizationBlob *)authorization; 259 260 xpc_dictionary_set_uint64(message, AUTH_XPC_TYPE, AUTHORIZATION_COPY_RIGHTS); 261 xpc_dictionary_set_data(message, AUTH_XPC_BLOB, blob, sizeof(AuthorizationBlob)); 262 setItemSet(message, AUTH_XPC_RIGHTS, rights); 263 setItemSet(message, AUTH_XPC_ENVIROMENT, environment); 264 xpc_dictionary_set_uint64(message, AUTH_XPC_FLAGS, flags); 265 266 *message_out = message; 267 message = NULL; 268 status = errAuthorizationSuccess; 269 270done: 271 xpc_release_safe(message); 272 return status; 273} 274 275OSStatus AuthorizationCopyRights(AuthorizationRef authorization, 276 const AuthorizationRights *rights, 277 const AuthorizationEnvironment *environment, 278 AuthorizationFlags flags, 279 AuthorizationRights **authorizedRights) 280{ 281 OSStatus status = errAuthorizationInternal; 282 xpc_object_t message = NULL; 283 284 require_noerr(status = _AuthorizationCopyRights_prepare_message(authorization, rights, environment, flags, &message), done); 285 require_noerr(status = _AuthorizationCopyRights_send_message(message, authorizedRights), done); 286 287done: 288 xpc_release_safe(message); 289 return status; 290} 291 292 293void AuthorizationCopyRightsAsync(AuthorizationRef authorization, 294 const AuthorizationRights *rights, 295 const AuthorizationEnvironment *environment, 296 AuthorizationFlags flags, 297 AuthorizationAsyncCallback callbackBlock) 298{ 299 OSStatus prepare_status = errAuthorizationInternal; 300 __block xpc_object_t message = NULL; 301 302 prepare_status = _AuthorizationCopyRights_prepare_message(authorization, rights, environment, flags, &message); 303 if (prepare_status != errAuthorizationSuccess) { 304 callbackBlock(prepare_status, NULL); 305 } 306 307 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 308 AuthorizationRights *blockAuthorizedRights = NULL; 309 OSStatus status = _AuthorizationCopyRights_send_message(message, &blockAuthorizedRights); 310 callbackBlock(status, blockAuthorizedRights); 311 xpc_release_safe(message); 312 }); 313} 314 315OSStatus AuthorizationDismiss() 316{ 317 OSStatus status = errAuthorizationInternal; 318 xpc_object_t message = NULL; 319 xpc_object_t reply = NULL; 320 321 // Send 322 message = xpc_dictionary_create(NULL, NULL, 0); 323 require(message != NULL, done); 324 325 xpc_dictionary_set_uint64(message, AUTH_XPC_TYPE, AUTHORIZATION_DISMISS); 326 327 // Reply 328 reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); 329 require_action(reply != NULL, done, status = errAuthorizationInternal); 330 require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); 331 332 // Status 333 status = (OSStatus)xpc_dictionary_get_int64(reply, AUTH_XPC_STATUS); 334 335done: 336 xpc_release_safe(message); 337 xpc_release_safe(reply); 338 return status; 339} 340 341OSStatus AuthorizationCopyInfo(AuthorizationRef authorization, 342 AuthorizationString tag, 343 AuthorizationItemSet **info) 344{ 345 OSStatus status = errAuthorizationInternal; 346 xpc_object_t message = NULL; 347 xpc_object_t reply = NULL; 348 AuthorizationBlob *blob = NULL; 349 350 require_action(info != NULL, done, status = errAuthorizationInvalidSet); 351 require_action(authorization != NULL, done, status = errAuthorizationInvalidRef); 352 blob = (AuthorizationBlob *)authorization; 353 354 // Send 355 message = xpc_dictionary_create(NULL, NULL, 0); 356 require_action(message != NULL, done, status = errAuthorizationInternal); 357 358 xpc_dictionary_set_uint64(message, AUTH_XPC_TYPE, AUTHORIZATION_COPY_INFO); 359 xpc_dictionary_set_data(message, AUTH_XPC_BLOB, blob, sizeof(AuthorizationBlob)); 360 if (tag) { 361 xpc_dictionary_set_string(message, AUTH_XPC_TAG, tag); 362 } 363 364 // Reply 365 reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); 366 require_action(reply != NULL, done, status = errAuthorizationInternal); 367 require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); 368 369 // Status 370 status = (OSStatus)xpc_dictionary_get_int64(reply, AUTH_XPC_STATUS); 371 372 // Out 373 if (info && status == errAuthorizationSuccess) { 374 xpc_object_t tmpItems = xpc_dictionary_get_value(reply, AUTH_XPC_OUT_ITEMS); 375 AuthorizationRights * outInfo = DeserializeItemSet(tmpItems); 376 require_action(outInfo != NULL, done, status = errAuthorizationInternal); 377 378 *info = outInfo; 379 } 380 381done: 382 xpc_release_safe(message); 383 xpc_release_safe(reply); 384 return status; 385} 386 387OSStatus AuthorizationMakeExternalForm(AuthorizationRef authorization, 388 AuthorizationExternalForm *extForm) 389{ 390 OSStatus status = errAuthorizationInternal; 391 xpc_object_t message = NULL; 392 xpc_object_t reply = NULL; 393 AuthorizationBlob *blob = NULL; 394 395 require_action(extForm != NULL, done, status = errAuthorizationInvalidPointer); 396 require_action(authorization != NULL, done, status = errAuthorizationInvalidRef); 397 blob = (AuthorizationBlob *)authorization; 398 399 // Send 400 message = xpc_dictionary_create(NULL, NULL, 0); 401 require_action(message != NULL, done, status = errAuthorizationInternal); 402 403 xpc_dictionary_set_uint64(message, AUTH_XPC_TYPE, AUTHORIZATION_MAKE_EXTERNAL_FORM); 404 xpc_dictionary_set_data(message, AUTH_XPC_BLOB, blob, sizeof(AuthorizationBlob)); 405 406 // Reply 407 reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); 408 require_action(reply != NULL, done, status = errAuthorizationInternal); 409 require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); 410 411 // Status 412 status = (OSStatus)xpc_dictionary_get_int64(reply, AUTH_XPC_STATUS); 413 414 // out 415 if (status == errAuthorizationSuccess) { 416 size_t len; 417 const void * data = xpc_dictionary_get_data(reply, AUTH_XPC_EXTERNAL, &len); 418 require_action(data != NULL, done, status = errAuthorizationInternal); 419 assert(len == sizeof(AuthorizationExternalForm)); 420 421 *extForm = *(AuthorizationExternalForm*)data; 422 } 423 424done: 425 xpc_release_safe(message); 426 xpc_release_safe(reply); 427 return status; 428} 429 430OSStatus AuthorizationCreateFromExternalForm(const AuthorizationExternalForm *extForm, 431 AuthorizationRef *authorization) 432{ 433 OSStatus status = errAuthorizationInternal; 434 xpc_object_t message = NULL; 435 xpc_object_t reply = NULL; 436 437 require_action(extForm != NULL, done, status = errAuthorizationInvalidPointer); 438 require_action(authorization != NULL, done, status = errAuthorizationInvalidRef); 439 440 // Send 441 message = xpc_dictionary_create(NULL, NULL, 0); 442 require_action(message != NULL, done, status = errAuthorizationInternal); 443 444 xpc_dictionary_set_uint64(message, AUTH_XPC_TYPE, AUTHORIZATION_CREATE_FROM_EXTERNAL_FORM); 445 xpc_dictionary_set_data(message, AUTH_XPC_EXTERNAL, extForm, sizeof(AuthorizationExternalForm)); 446 447 // Reply 448 reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); 449 require_action(reply != NULL, done, status = errAuthorizationInternal); 450 require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); 451 452 // Status 453 status = (OSStatus)xpc_dictionary_get_int64(reply, AUTH_XPC_STATUS); 454 455 // Out 456 if (authorization && status == errAuthorizationSuccess) { 457 size_t len; 458 const void * data = xpc_dictionary_get_data(reply, AUTH_XPC_BLOB, &len); 459 require_action(data != NULL, done, status = errAuthorizationInternal); 460 assert(len == sizeof(AuthorizationBlob)); 461 462 AuthorizationBlob * blob = (AuthorizationBlob*)calloc(1u, sizeof(AuthorizationBlob)); 463 require_action(blob != NULL, done, status = errAuthorizationInternal); 464 *blob = *(AuthorizationBlob*)data; 465 466 *authorization = (AuthorizationRef)blob; 467 } 468 469done: 470 xpc_release_safe(message); 471 xpc_release_safe(reply); 472 return status; 473} 474 475OSStatus AuthorizationFreeItemSet(AuthorizationItemSet *set) 476{ 477 FreeItemSet(set); 478 return errAuthorizationSuccess; 479} 480 481OSStatus AuthorizationEnableSmartCard(AuthorizationRef authRef, Boolean enable) 482{ 483 OSStatus status = errAuthorizationInternal; 484 xpc_object_t message = NULL; 485 xpc_object_t reply = NULL; 486 AuthorizationBlob *blob = NULL; 487 488 // Send 489 message = xpc_dictionary_create(NULL, NULL, 0); 490 require_action(message != NULL, done, status = errAuthorizationInternal); 491 require_action(authRef != NULL, done, status = errAuthorizationInvalidRef); 492 blob = (AuthorizationBlob *)authRef; 493 xpc_dictionary_set_uint64(message, AUTH_XPC_TYPE, AUTHORIZATION_ENABLE_SMARTCARD); 494 xpc_dictionary_set_data(message, AUTH_XPC_BLOB, blob, sizeof(AuthorizationBlob)); 495 xpc_dictionary_set_bool(message, AUTH_XPC_DATA, enable); 496 497 // Reply 498 reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); 499 require_action(reply != NULL, done, status = errAuthorizationInternal); 500 require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); 501 502 status = (OSStatus)xpc_dictionary_get_int64(reply, AUTH_XPC_STATUS); 503 504done: 505 xpc_release_safe(message); 506 xpc_release_safe(reply); 507 return status; 508} 509 510 511OSStatus AuthorizationRightGet(const char *rightName, 512 CFDictionaryRef *rightDefinition) 513{ 514 OSStatus status = errAuthorizationInternal; 515 xpc_object_t message = NULL; 516 xpc_object_t reply = NULL; 517 518 require_action(rightName != NULL, done, status = errAuthorizationInvalidPointer); 519 520 // Send 521 message = xpc_dictionary_create(NULL, NULL, 0); 522 require_action(message != NULL, done, status = errAuthorizationInternal); 523 524 xpc_dictionary_set_uint64(message, AUTH_XPC_TYPE, AUTHORIZATION_RIGHT_GET); 525 xpc_dictionary_set_string(message, AUTH_XPC_RIGHT_NAME, rightName); 526 527 // Reply 528 reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); 529 require_action(reply != NULL, done, status = errAuthorizationInternal); 530 require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); 531 532 // Status 533 status = (OSStatus)xpc_dictionary_get_int64(reply, AUTH_XPC_STATUS); 534 535 // Out 536 if (rightDefinition && status == errAuthorizationSuccess) { 537 xpc_object_t value = xpc_dictionary_get_value(reply, AUTH_XPC_DATA); 538 require_action(value != NULL, done, status = errAuthorizationInternal); 539 require_action(xpc_get_type(value) == XPC_TYPE_DICTIONARY, done, status = errAuthorizationInternal); 540 541 CFTypeRef cfdict = _CFXPCCreateCFObjectFromXPCObject(value); 542 require_action(cfdict != NULL, done, status = errAuthorizationInternal); 543 544 *rightDefinition = cfdict; 545 } 546 547done: 548 xpc_release_safe(message); 549 xpc_release_safe(reply); 550 return status; 551} 552 553OSStatus AuthorizationRightSet(AuthorizationRef authRef, 554 const char *rightName, 555 CFTypeRef rightDefinition, 556 CFStringRef descriptionKey, 557 CFBundleRef bundle, 558 CFStringRef tableName) 559{ 560 OSStatus status = errAuthorizationInternal; 561 xpc_object_t message = NULL; 562 xpc_object_t reply = NULL; 563 AuthorizationBlob *blob = NULL; 564 CFMutableDictionaryRef rightDict = NULL; 565 CFBundleRef clientBundle = bundle; 566 567 if (bundle) { 568 CFRetain(bundle); 569 } 570 571 require_action(rightDefinition != NULL, done, status = errAuthorizationInvalidPointer); 572 require_action(rightName != NULL, done, status = errAuthorizationInvalidPointer); 573 require_action(authRef != NULL, done, status = errAuthorizationInvalidRef); 574 blob = (AuthorizationBlob *)authRef; 575 576 // Send 577 message = xpc_dictionary_create(NULL, NULL, 0); 578 require_action(message != NULL, done, status = errAuthorizationInternal); 579 580 xpc_dictionary_set_uint64(message, AUTH_XPC_TYPE, AUTHORIZATION_RIGHT_SET); 581 xpc_dictionary_set_data(message, AUTH_XPC_BLOB, blob, sizeof(AuthorizationBlob)); 582 xpc_dictionary_set_string(message, AUTH_XPC_RIGHT_NAME, rightName); 583 584 // Create rightDict 585 if (CFGetTypeID(rightDefinition) == CFStringGetTypeID()) { 586 rightDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 587 require_action(rightDict != NULL, done, status = errAuthorizationInternal); 588 589 CFDictionarySetValue(rightDict, CFSTR(kAuthorizationRightRule), rightDefinition); 590 591 } else if (CFGetTypeID(rightDefinition) == CFDictionaryGetTypeID()) { 592 rightDict = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, rightDefinition); 593 require_action(rightDict != NULL, done, status = errAuthorizationInternal); 594 595 } else { 596 status = errAuthorizationInvalidPointer; 597 goto done; 598 } 599 600 // Create locDict 601 if (descriptionKey) { 602 CFMutableDictionaryRef locDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 603 require_action(locDict != NULL, done, status = errAuthorizationInternal); 604 605 if (clientBundle == NULL) { 606 clientBundle = CFBundleGetMainBundle(); 607 CFRetain(clientBundle); 608 } 609 610 if (clientBundle) { 611 CFArrayRef bundleLocalizations = CFBundleCopyBundleLocalizations(clientBundle); 612 if (bundleLocalizations) { 613 // for every CFString in localizations do 614 CFIndex locIndex, allLocs = CFArrayGetCount(bundleLocalizations); 615 for (locIndex = 0; locIndex < allLocs; locIndex++) 616 { 617 CFStringRef oneLocalization = (CFStringRef)CFArrayGetValueAtIndex(bundleLocalizations, locIndex); 618 619 if (!oneLocalization) 620 continue; 621 622 // @@@ no way to get "Localized" and "strings" as constants? 623 CFURLRef locURL = CFBundleCopyResourceURLForLocalization(clientBundle, tableName ? tableName : CFSTR("Localizable"), CFSTR("strings"), NULL /*subDirName*/, oneLocalization); 624 625 if (!locURL) 626 continue; 627 628 CFDataRef tableData = NULL; 629 SInt32 errCode; 630 CFStringRef errStr = NULL; 631 CFPropertyListRef stringTable = NULL; 632 633 CFURLCreateDataAndPropertiesFromResource(CFGetAllocator(clientBundle), locURL, &tableData, NULL, NULL, &errCode); 634 CFReleaseSafe(locURL); 635 if (errCode) 636 { 637 CFReleaseSafe(tableData); 638 continue; 639 } 640 641 stringTable = CFPropertyListCreateFromXMLData(CFGetAllocator(clientBundle), tableData, kCFPropertyListImmutable, &errStr); 642 CFReleaseSafe(errStr); 643 CFReleaseSafe(tableData); 644 645 CFStringRef value = (CFStringRef)CFDictionaryGetValue(stringTable, descriptionKey); 646 if (value == NULL || CFEqual(value, CFSTR(""))) { 647 CFReleaseSafe(stringTable); 648 continue; 649 } else { 650 // oneLocalization/value into our dictionary 651 CFDictionarySetValue(locDict, oneLocalization, value); 652 CFReleaseSafe(stringTable); 653 } 654 } 655 CFReleaseSafe(bundleLocalizations); 656 } 657 } 658 659 // add the description as the default localization into the dictionary 660 CFDictionarySetValue(locDict, CFSTR(""), descriptionKey); 661 662 // stuff localization table into right definition 663 CFDictionarySetValue(rightDict, CFSTR(kAuthorizationRuleParameterDefaultPrompt), locDict); 664 CFReleaseSafe(locDict); 665 } 666 667 xpc_object_t value = _CFXPCCreateXPCObjectFromCFObject(rightDict); 668 xpc_dictionary_set_value(message, AUTH_XPC_DATA, value); 669 xpc_release_safe(value); 670 671 // Reply 672 reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); 673 require_action(reply != NULL, done, status = errAuthorizationInternal); 674 require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); 675 676 // Status 677 status = (OSStatus)xpc_dictionary_get_int64(reply, AUTH_XPC_STATUS); 678 679done: 680 CFReleaseSafe(clientBundle); 681 CFReleaseSafe(rightDict); 682 xpc_release_safe(message); 683 xpc_release_safe(reply); 684 return status; 685} 686 687OSStatus AuthorizationRightRemove(AuthorizationRef authorization, 688 const char *rightName) 689{ 690 OSStatus status = errAuthorizationInternal; 691 xpc_object_t message = NULL; 692 xpc_object_t reply = NULL; 693 AuthorizationBlob *blob = NULL; 694 695 require_action(rightName != NULL, done, status = errAuthorizationInvalidPointer); 696 require_action(authorization != NULL, done, status = errAuthorizationInvalidRef); 697 blob = (AuthorizationBlob *)authorization; 698 699 // Send 700 message = xpc_dictionary_create(NULL, NULL, 0); 701 require_action(message != NULL, done, status = errAuthorizationInternal); 702 703 xpc_dictionary_set_uint64(message, AUTH_XPC_TYPE, AUTHORIZATION_RIGHT_REMOVE); 704 xpc_dictionary_set_data(message, AUTH_XPC_BLOB, blob, sizeof(AuthorizationBlob)); 705 xpc_dictionary_set_string(message, AUTH_XPC_RIGHT_NAME, rightName); 706 707 // Reply 708 reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message); 709 require_action(reply != NULL, done, status = errAuthorizationInternal); 710 require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal); 711 712 // Status 713 status = (OSStatus)xpc_dictionary_get_int64(reply, AUTH_XPC_STATUS); 714 715done: 716 xpc_release_safe(message); 717 xpc_release_safe(reply); 718 return status; 719} 720