]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_authorization/lib/Authorization.c
Security-58286.31.2.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 _AuthorizationPreauthorizeCredentials_send_message(xpc_object_t message)
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 done:
236 xpc_release_safe(reply);
237 return status;
238 }
239
240 static OSStatus
241 _AuthorizationPreauthorizeCredentials_prepare_message(AuthorizationRef authorization, const AuthorizationItemSet *credentials, xpc_object_t *message_out)
242 {
243 OSStatus status = errAuthorizationInternal;
244 AuthorizationBlob *blob = NULL;
245 xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);
246 require_action(message != NULL, done, status = errAuthorizationInternal);
247
248 require_action(authorization != NULL, done, status = errAuthorizationInvalidRef);
249 blob = (AuthorizationBlob *)authorization;
250
251 xpc_dictionary_set_uint64(message, AUTH_XPC_TYPE, AUTHORIZATION_PREAUTHORIZE_CREDENTIALS);
252 xpc_dictionary_set_data(message, AUTH_XPC_BLOB, blob, sizeof(AuthorizationBlob));
253 setItemSet(message, AUTH_XPC_DATA, credentials);
254
255 *message_out = message;
256 message = NULL;
257 status = errAuthorizationSuccess;
258
259 done:
260 xpc_release_safe(message);
261 return status;
262 }
263
264 OSStatus AuthorizationPreauthorizeCredentials(AuthorizationRef authorization, const AuthorizationItemSet *credentials)
265 {
266 OSStatus status = errAuthorizationInternal;
267 xpc_object_t message = NULL;
268
269 require_noerr(status = _AuthorizationPreauthorizeCredentials_prepare_message(authorization, credentials, &message), done);
270 require_noerr(status = _AuthorizationPreauthorizeCredentials_send_message(message), done);
271
272 done:
273 xpc_release_safe(message);
274 return status;
275 }
276
277 static OSStatus
278 _AuthorizationCopyRights_send_message(xpc_object_t message, AuthorizationRights **authorizedRights)
279 {
280 OSStatus status = errAuthorizationInternal;
281 xpc_object_t reply = NULL;
282
283 // Send
284 require_action(message != NULL, done, status = errAuthorizationInternal);
285
286 // Reply
287 reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message);
288 require_action(reply != NULL, done, status = errAuthorizationInternal);
289 require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal);
290
291 // Status
292 status = (OSStatus)xpc_dictionary_get_int64(reply, AUTH_XPC_STATUS);
293
294 // Out
295 if (authorizedRights && status == errAuthorizationSuccess) {
296 xpc_object_t tmpItems = xpc_dictionary_get_value(reply, AUTH_XPC_OUT_ITEMS);
297 AuthorizationRights * grantedRights = DeserializeItemSet(tmpItems);
298 require_action(grantedRights != NULL, done, status = errAuthorizationInternal);
299
300 *authorizedRights = grantedRights;
301 }
302
303 done:
304 xpc_release_safe(reply);
305 return status;
306 }
307
308 static OSStatus
309 _AuthorizationCopyRights_prepare_message(AuthorizationRef authorization, const AuthorizationRights *rights, const AuthorizationEnvironment *environment, AuthorizationFlags flags, xpc_object_t *message_out)
310 {
311 OSStatus status = errAuthorizationInternal;
312 AuthorizationBlob *blob = NULL;
313 xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);
314 require_action(message != NULL, done, status = errAuthorizationInternal);
315
316 require_action(authorization != NULL, done, status = errAuthorizationInvalidRef);
317 blob = (AuthorizationBlob *)authorization;
318
319 xpc_dictionary_set_uint64(message, AUTH_XPC_TYPE, AUTHORIZATION_COPY_RIGHTS);
320 xpc_dictionary_set_data(message, AUTH_XPC_BLOB, blob, sizeof(AuthorizationBlob));
321 setItemSet(message, AUTH_XPC_RIGHTS, rights);
322 setItemSet(message, AUTH_XPC_ENVIRONMENT, environment);
323 xpc_dictionary_set_uint64(message, AUTH_XPC_FLAGS, flags);
324
325 *message_out = message;
326 message = NULL;
327 status = errAuthorizationSuccess;
328
329 done:
330 xpc_release_safe(message);
331 return status;
332 }
333
334 OSStatus AuthorizationCopyRights(AuthorizationRef authorization,
335 const AuthorizationRights *rights,
336 const AuthorizationEnvironment *environment,
337 AuthorizationFlags flags,
338 AuthorizationRights **authorizedRights)
339 {
340 OSStatus status = errAuthorizationInternal;
341 xpc_object_t message = NULL;
342
343 require_noerr(status = _AuthorizationCopyRights_prepare_message(authorization, rights, environment, flags, &message), done);
344 require_noerr(status = _AuthorizationCopyRights_send_message(message, authorizedRights), done);
345
346 done:
347 xpc_release_safe(message);
348 return status;
349 }
350
351
352 void AuthorizationCopyRightsAsync(AuthorizationRef authorization,
353 const AuthorizationRights *rights,
354 const AuthorizationEnvironment *environment,
355 AuthorizationFlags flags,
356 AuthorizationAsyncCallback callbackBlock)
357 {
358 OSStatus prepare_status = errAuthorizationInternal;
359 __block xpc_object_t message = NULL;
360
361 prepare_status = _AuthorizationCopyRights_prepare_message(authorization, rights, environment, flags, &message);
362 if (prepare_status != errAuthorizationSuccess) {
363 callbackBlock(prepare_status, NULL);
364 }
365
366 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
367 AuthorizationRights *blockAuthorizedRights = NULL;
368 OSStatus status = _AuthorizationCopyRights_send_message(message, &blockAuthorizedRights);
369 callbackBlock(status, blockAuthorizedRights);
370 xpc_release_safe(message);
371 });
372 }
373
374 OSStatus AuthorizationDismiss()
375 {
376 OSStatus status = errAuthorizationInternal;
377 xpc_object_t message = NULL;
378 xpc_object_t reply = NULL;
379
380 // Send
381 message = xpc_dictionary_create(NULL, NULL, 0);
382 require(message != NULL, done);
383
384 xpc_dictionary_set_uint64(message, AUTH_XPC_TYPE, AUTHORIZATION_DISMISS);
385
386 // Reply
387 reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message);
388 require_action(reply != NULL, done, status = errAuthorizationInternal);
389 require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal);
390
391 // Status
392 status = (OSStatus)xpc_dictionary_get_int64(reply, AUTH_XPC_STATUS);
393
394 done:
395 xpc_release_safe(message);
396 xpc_release_safe(reply);
397 return status;
398 }
399
400 OSStatus AuthorizationCopyInfo(AuthorizationRef authorization,
401 AuthorizationString tag,
402 AuthorizationItemSet **info)
403 {
404 OSStatus status = errAuthorizationInternal;
405 xpc_object_t message = NULL;
406 xpc_object_t reply = NULL;
407 AuthorizationBlob *blob = NULL;
408
409 require_action(info != NULL, done, status = errAuthorizationInvalidSet);
410 require_action(authorization != NULL, done, status = errAuthorizationInvalidRef);
411 blob = (AuthorizationBlob *)authorization;
412
413 // Send
414 message = xpc_dictionary_create(NULL, NULL, 0);
415 require_action(message != NULL, done, status = errAuthorizationInternal);
416
417 xpc_dictionary_set_uint64(message, AUTH_XPC_TYPE, AUTHORIZATION_COPY_INFO);
418 xpc_dictionary_set_data(message, AUTH_XPC_BLOB, blob, sizeof(AuthorizationBlob));
419 if (tag) {
420 xpc_dictionary_set_string(message, AUTH_XPC_TAG, tag);
421 }
422
423 // Reply
424 reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message);
425 require_action(reply != NULL, done, status = errAuthorizationInternal);
426 require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal);
427
428 // Status
429 status = (OSStatus)xpc_dictionary_get_int64(reply, AUTH_XPC_STATUS);
430
431 // Out
432 if (info && status == errAuthorizationSuccess) {
433 xpc_object_t tmpItems = xpc_dictionary_get_value(reply, AUTH_XPC_OUT_ITEMS);
434 AuthorizationRights * outInfo = DeserializeItemSet(tmpItems);
435 require_action(outInfo != NULL, done, status = errAuthorizationInternal);
436
437 *info = outInfo;
438 }
439
440 done:
441 xpc_release_safe(message);
442 xpc_release_safe(reply);
443 return status;
444 }
445
446 OSStatus AuthorizationMakeExternalForm(AuthorizationRef authorization,
447 AuthorizationExternalForm *extForm)
448 {
449 OSStatus status = errAuthorizationInternal;
450 xpc_object_t message = NULL;
451 xpc_object_t reply = NULL;
452 AuthorizationBlob *blob = NULL;
453
454 require_action(extForm != NULL, done, status = errAuthorizationInvalidPointer);
455 require_action(authorization != NULL, done, status = errAuthorizationInvalidRef);
456 blob = (AuthorizationBlob *)authorization;
457
458 // Send
459 message = xpc_dictionary_create(NULL, NULL, 0);
460 require_action(message != NULL, done, status = errAuthorizationInternal);
461
462 xpc_dictionary_set_uint64(message, AUTH_XPC_TYPE, AUTHORIZATION_MAKE_EXTERNAL_FORM);
463 xpc_dictionary_set_data(message, AUTH_XPC_BLOB, blob, sizeof(AuthorizationBlob));
464
465 // Reply
466 reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message);
467 require_action(reply != NULL, done, status = errAuthorizationInternal);
468 require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal);
469
470 // Status
471 status = (OSStatus)xpc_dictionary_get_int64(reply, AUTH_XPC_STATUS);
472
473 // out
474 if (status == errAuthorizationSuccess) {
475 size_t len;
476 const void * data = xpc_dictionary_get_data(reply, AUTH_XPC_EXTERNAL, &len);
477 require_action(data != NULL, done, status = errAuthorizationInternal);
478 assert(len == sizeof(AuthorizationExternalForm));
479
480 *extForm = *(AuthorizationExternalForm*)data;
481 }
482
483 done:
484 xpc_release_safe(message);
485 xpc_release_safe(reply);
486 return status;
487 }
488
489 OSStatus AuthorizationCreateFromExternalForm(const AuthorizationExternalForm *extForm,
490 AuthorizationRef *authorization)
491 {
492 OSStatus status = errAuthorizationInternal;
493 xpc_object_t message = NULL;
494 xpc_object_t reply = NULL;
495
496 require_action(extForm != NULL, done, status = errAuthorizationInvalidPointer);
497 require_action(authorization != NULL, done, status = errAuthorizationInvalidRef);
498
499 // Send
500 message = xpc_dictionary_create(NULL, NULL, 0);
501 require_action(message != NULL, done, status = errAuthorizationInternal);
502
503 xpc_dictionary_set_uint64(message, AUTH_XPC_TYPE, AUTHORIZATION_CREATE_FROM_EXTERNAL_FORM);
504 xpc_dictionary_set_data(message, AUTH_XPC_EXTERNAL, extForm, sizeof(AuthorizationExternalForm));
505
506 // Reply
507 reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message);
508 require_action(reply != NULL, done, status = errAuthorizationInternal);
509 require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal);
510
511 // Status
512 status = (OSStatus)xpc_dictionary_get_int64(reply, AUTH_XPC_STATUS);
513
514 // Out
515 if (authorization && status == errAuthorizationSuccess) {
516 size_t len;
517 const void * data = xpc_dictionary_get_data(reply, AUTH_XPC_BLOB, &len);
518 require_action(data != NULL, done, status = errAuthorizationInternal);
519 assert(len == sizeof(AuthorizationBlob));
520
521 AuthorizationBlob * blob = (AuthorizationBlob*)calloc(1u, sizeof(AuthorizationBlob));
522 require_action(blob != NULL, done, status = errAuthorizationInternal);
523 *blob = *(AuthorizationBlob*)data;
524
525 *authorization = (AuthorizationRef)blob;
526 }
527
528 done:
529 xpc_release_safe(message);
530 xpc_release_safe(reply);
531 return status;
532 }
533
534 OSStatus AuthorizationFreeItemSet(AuthorizationItemSet *set)
535 {
536 FreeItemSet(set);
537 return errAuthorizationSuccess;
538 }
539
540 OSStatus AuthorizationEnableSmartCard(AuthorizationRef authRef, Boolean enable)
541 {
542 OSStatus status = errAuthorizationInternal;
543 xpc_object_t message = NULL;
544 xpc_object_t reply = NULL;
545 AuthorizationBlob *blob = NULL;
546
547 // Send
548 message = xpc_dictionary_create(NULL, NULL, 0);
549 require_action(message != NULL, done, status = errAuthorizationInternal);
550 require_action(authRef != NULL, done, status = errAuthorizationInvalidRef);
551 blob = (AuthorizationBlob *)authRef;
552 xpc_dictionary_set_uint64(message, AUTH_XPC_TYPE, AUTHORIZATION_ENABLE_SMARTCARD);
553 xpc_dictionary_set_data(message, AUTH_XPC_BLOB, blob, sizeof(AuthorizationBlob));
554 xpc_dictionary_set_bool(message, AUTH_XPC_DATA, enable);
555
556 // Reply
557 reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message);
558 require_action(reply != NULL, done, status = errAuthorizationInternal);
559 require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal);
560
561 status = (OSStatus)xpc_dictionary_get_int64(reply, AUTH_XPC_STATUS);
562
563 done:
564 xpc_release_safe(message);
565 xpc_release_safe(reply);
566 return status;
567 }
568
569
570 OSStatus AuthorizationRightGet(const char *rightName,
571 CFDictionaryRef *rightDefinition)
572 {
573 OSStatus status = errAuthorizationInternal;
574 xpc_object_t message = NULL;
575 xpc_object_t reply = NULL;
576
577 require_action(rightName != NULL, done, status = errAuthorizationInvalidPointer);
578
579 // Send
580 message = xpc_dictionary_create(NULL, NULL, 0);
581 require_action(message != NULL, done, status = errAuthorizationInternal);
582
583 xpc_dictionary_set_uint64(message, AUTH_XPC_TYPE, AUTHORIZATION_RIGHT_GET);
584 xpc_dictionary_set_string(message, AUTH_XPC_RIGHT_NAME, rightName);
585
586 // Reply
587 reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message);
588 require_action(reply != NULL, done, status = errAuthorizationInternal);
589 require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal);
590
591 // Status
592 status = (OSStatus)xpc_dictionary_get_int64(reply, AUTH_XPC_STATUS);
593
594 // Out
595 if (rightDefinition && status == errAuthorizationSuccess) {
596 xpc_object_t value = xpc_dictionary_get_value(reply, AUTH_XPC_DATA);
597 require_action(value != NULL, done, status = errAuthorizationInternal);
598 require_action(xpc_get_type(value) == XPC_TYPE_DICTIONARY, done, status = errAuthorizationInternal);
599
600 CFTypeRef cfdict = _CFXPCCreateCFObjectFromXPCObject(value);
601 require_action(cfdict != NULL, done, status = errAuthorizationInternal);
602
603 *rightDefinition = cfdict;
604 }
605
606 done:
607 xpc_release_safe(message);
608 xpc_release_safe(reply);
609 return status;
610 }
611
612 OSStatus AuthorizationRightSet(AuthorizationRef authRef,
613 const char *rightName,
614 CFTypeRef rightDefinition,
615 CFStringRef descriptionKey,
616 CFBundleRef bundle,
617 CFStringRef tableName)
618 {
619 OSStatus status = errAuthorizationInternal;
620 xpc_object_t message = NULL;
621 xpc_object_t reply = NULL;
622 AuthorizationBlob *blob = NULL;
623 CFMutableDictionaryRef rightDict = NULL;
624 CFBundleRef clientBundle = bundle;
625
626 if (bundle) {
627 CFRetain(bundle);
628 }
629
630 require_action(rightDefinition != NULL, done, status = errAuthorizationInvalidPointer);
631 require_action(rightName != NULL, done, status = errAuthorizationInvalidPointer);
632 require_action(authRef != NULL, done, status = errAuthorizationInvalidRef);
633 blob = (AuthorizationBlob *)authRef;
634
635 // Send
636 message = xpc_dictionary_create(NULL, NULL, 0);
637 require_action(message != NULL, done, status = errAuthorizationInternal);
638
639 xpc_dictionary_set_uint64(message, AUTH_XPC_TYPE, AUTHORIZATION_RIGHT_SET);
640 xpc_dictionary_set_data(message, AUTH_XPC_BLOB, blob, sizeof(AuthorizationBlob));
641 xpc_dictionary_set_string(message, AUTH_XPC_RIGHT_NAME, rightName);
642
643 // Create rightDict
644 if (CFGetTypeID(rightDefinition) == CFStringGetTypeID()) {
645 rightDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
646 require_action(rightDict != NULL, done, status = errAuthorizationInternal);
647
648 CFDictionarySetValue(rightDict, CFSTR(kAuthorizationRightRule), rightDefinition);
649
650 } else if (CFGetTypeID(rightDefinition) == CFDictionaryGetTypeID()) {
651 rightDict = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, rightDefinition);
652 require_action(rightDict != NULL, done, status = errAuthorizationInternal);
653
654 } else {
655 status = errAuthorizationInvalidPointer;
656 goto done;
657 }
658
659 // Create locDict
660 if (descriptionKey) {
661 CFMutableDictionaryRef locDict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
662 require_action(locDict != NULL, done, status = errAuthorizationInternal);
663
664 if (clientBundle == NULL) {
665 clientBundle = CFBundleGetMainBundle();
666 CFRetain(clientBundle);
667 }
668
669 if (clientBundle) {
670 CFArrayRef bundleLocalizations = CFBundleCopyBundleLocalizations(clientBundle);
671 if (bundleLocalizations) {
672 // for every CFString in localizations do
673 CFIndex locIndex, allLocs = CFArrayGetCount(bundleLocalizations);
674 for (locIndex = 0; locIndex < allLocs; locIndex++)
675 {
676 CFStringRef oneLocalization = (CFStringRef)CFArrayGetValueAtIndex(bundleLocalizations, locIndex);
677
678 if (!oneLocalization)
679 continue;
680
681 // @@@ no way to get "Localized" and "strings" as constants?
682 CFURLRef locURL = CFBundleCopyResourceURLForLocalization(clientBundle, tableName ? tableName : CFSTR("Localizable"), CFSTR("strings"), NULL /*subDirName*/, oneLocalization);
683
684 if (!locURL)
685 continue;
686
687 CFDataRef tableData = NULL;
688 SInt32 errCode;
689 CFStringRef errStr = NULL;
690 CFPropertyListRef stringTable = NULL;
691
692 CFURLCreateDataAndPropertiesFromResource(CFGetAllocator(clientBundle), locURL, &tableData, NULL, NULL, &errCode);
693 CFReleaseSafe(locURL);
694 if (errCode)
695 {
696 CFReleaseSafe(tableData);
697 continue;
698 }
699
700 stringTable = CFPropertyListCreateFromXMLData(CFGetAllocator(clientBundle), tableData, kCFPropertyListImmutable, &errStr);
701 CFReleaseSafe(errStr);
702 CFReleaseSafe(tableData);
703
704 CFStringRef value = (CFStringRef)CFDictionaryGetValue(stringTable, descriptionKey);
705 if (value == NULL || CFEqual(value, CFSTR(""))) {
706 CFReleaseSafe(stringTable);
707 continue;
708 } else {
709 // oneLocalization/value into our dictionary
710 CFDictionarySetValue(locDict, oneLocalization, value);
711 CFReleaseSafe(stringTable);
712 }
713 }
714 CFReleaseSafe(bundleLocalizations);
715 }
716 }
717
718 // add the description as the default localization into the dictionary
719 CFDictionarySetValue(locDict, CFSTR(""), descriptionKey);
720
721 // stuff localization table into right definition
722 CFDictionarySetValue(rightDict, CFSTR(kAuthorizationRuleParameterDefaultPrompt), locDict);
723 CFReleaseSafe(locDict);
724 }
725
726 xpc_object_t value = _CFXPCCreateXPCObjectFromCFObject(rightDict);
727 xpc_dictionary_set_value(message, AUTH_XPC_DATA, value);
728 xpc_release_safe(value);
729
730 // Reply
731 reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message);
732 require_action(reply != NULL, done, status = errAuthorizationInternal);
733 require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal);
734
735 // Status
736 status = (OSStatus)xpc_dictionary_get_int64(reply, AUTH_XPC_STATUS);
737
738 done:
739 CFReleaseSafe(clientBundle);
740 CFReleaseSafe(rightDict);
741 xpc_release_safe(message);
742 xpc_release_safe(reply);
743 return status;
744 }
745
746 OSStatus AuthorizationRightRemove(AuthorizationRef authorization,
747 const char *rightName)
748 {
749 OSStatus status = errAuthorizationInternal;
750 xpc_object_t message = NULL;
751 xpc_object_t reply = NULL;
752 AuthorizationBlob *blob = NULL;
753
754 require_action(rightName != NULL, done, status = errAuthorizationInvalidPointer);
755 require_action(authorization != NULL, done, status = errAuthorizationInvalidRef);
756 blob = (AuthorizationBlob *)authorization;
757
758 // Send
759 message = xpc_dictionary_create(NULL, NULL, 0);
760 require_action(message != NULL, done, status = errAuthorizationInternal);
761
762 xpc_dictionary_set_uint64(message, AUTH_XPC_TYPE, AUTHORIZATION_RIGHT_REMOVE);
763 xpc_dictionary_set_data(message, AUTH_XPC_BLOB, blob, sizeof(AuthorizationBlob));
764 xpc_dictionary_set_string(message, AUTH_XPC_RIGHT_NAME, rightName);
765
766 // Reply
767 reply = xpc_connection_send_message_with_reply_sync(get_authorization_connection(), message);
768 require_action(reply != NULL, done, status = errAuthorizationInternal);
769 require_action(xpc_get_type(reply) != XPC_TYPE_ERROR, done, status = errAuthorizationInternal);
770
771 // Status
772 status = (OSStatus)xpc_dictionary_get_int64(reply, AUTH_XPC_STATUS);
773
774 done:
775 xpc_release_safe(message);
776 xpc_release_safe(reply);
777 return status;
778 }