]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_authorization/lib/Authorization.c
Security-57740.51.3.tar.gz
[apple/security.git] / OSX / libsecurity_authorization / lib / Authorization.c
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
19 static dispatch_queue_t
20 get_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
32 static xpc_connection_t
33 get_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
77 static void
78 setItemSet(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
87 OSStatus 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_ENVIRONMENT, 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_quiet(reply != NULL, done, status = errAuthorizationInternal);
110 require_action_quiet(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
129 done:
130 xpc_release_safe(message);
131 xpc_release_safe(reply);
132 return status;
133 }
134
135 OSStatus 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_ENVIRONMENT, 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
177 done:
178 xpc_release_safe(message);
179 xpc_release_safe(reply);
180 return status;
181 }
182
183 OSStatus 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
212 done:
213 xpc_release_safe(message);
214 xpc_release_safe(reply);
215 return status;
216 }
217
218 static 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
244 done:
245 xpc_release_safe(reply);
246 return status;
247 }
248
249 static 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_ENVIRONMENT, environment);
264 xpc_dictionary_set_uint64(message, AUTH_XPC_FLAGS, flags);
265
266 *message_out = message;
267 message = NULL;
268 status = errAuthorizationSuccess;
269
270 done:
271 xpc_release_safe(message);
272 return status;
273 }
274
275 OSStatus 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
287 done:
288 xpc_release_safe(message);
289 return status;
290 }
291
292
293 void 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
315 OSStatus 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
335 done:
336 xpc_release_safe(message);
337 xpc_release_safe(reply);
338 return status;
339 }
340
341 OSStatus 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
381 done:
382 xpc_release_safe(message);
383 xpc_release_safe(reply);
384 return status;
385 }
386
387 OSStatus 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
424 done:
425 xpc_release_safe(message);
426 xpc_release_safe(reply);
427 return status;
428 }
429
430 OSStatus 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
469 done:
470 xpc_release_safe(message);
471 xpc_release_safe(reply);
472 return status;
473 }
474
475 OSStatus AuthorizationFreeItemSet(AuthorizationItemSet *set)
476 {
477 FreeItemSet(set);
478 return errAuthorizationSuccess;
479 }
480
481 OSStatus 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
504 done:
505 xpc_release_safe(message);
506 xpc_release_safe(reply);
507 return status;
508 }
509
510
511 OSStatus 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
547 done:
548 xpc_release_safe(message);
549 xpc_release_safe(reply);
550 return status;
551 }
552
553 OSStatus 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
679 done:
680 CFReleaseSafe(clientBundle);
681 CFReleaseSafe(rightDict);
682 xpc_release_safe(message);
683 xpc_release_safe(reply);
684 return status;
685 }
686
687 OSStatus 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
715 done:
716 xpc_release_safe(message);
717 xpc_release_safe(reply);
718 return status;
719 }