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