]> git.saurik.com Git - apple/security.git/blob - OSX/authd/server.c
Security-58286.200.222.tar.gz
[apple/security.git] / OSX / authd / server.c
1 /* Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */
2
3 #include "server.h"
4 #include "session.h"
5 #include "process.h"
6 #include "authtoken.h"
7 #include "authdb.h"
8 #include "rule.h"
9 #include "authutilities.h"
10 #include "crc.h"
11 #include "mechanism.h"
12 #include "agent.h"
13 #include "authitems.h"
14 #include "debugging.h"
15 #include "engine.h"
16 #include "connection.h"
17
18 #include <bsm/libbsm.h>
19 #include <Security/Authorization.h>
20 #include <Security/AuthorizationPriv.h>
21 #include <Security/AuthorizationTagsPriv.h>
22 #include <Security/AuthorizationPlugin.h>
23 #include <xpc/private.h>
24 #include <dispatch/dispatch.h>
25 #include <CoreFoundation/CoreFoundation.h>
26 #include <CoreFoundation/CFXPCBridge.h>
27 #include <IOKit/IOMessage.h>
28 #include <IOKit/pwr_mgt/IOPMLib.h>
29 #include <IOKit/pwr_mgt/IOPMLibPrivate.h>
30
31 AUTHD_DEFINE_LOG
32
33 #define MAX_PROCESS_RIGHTS 100
34
35 static CFMutableDictionaryRef gProcessMap = NULL;
36 static CFMutableDictionaryRef gSessionMap = NULL;
37 static CFMutableDictionaryRef gAuthTokenMap = NULL;
38 static authdb_t gDatabase = NULL;
39
40 static dispatch_queue_t power_queue;
41 static bool gInDarkWake = false;
42 static IOPMConnection gIOPMconn = NULL;
43 static bool gXPCTransaction = false;
44
45 static dispatch_queue_t
46 get_server_dispatch_queue()
47 {
48 static dispatch_once_t onceToken;
49 static dispatch_queue_t server_queue = NULL;
50
51 dispatch_once(&onceToken, ^{
52 server_queue = dispatch_queue_create("com.apple.security.auth.server", DISPATCH_QUEUE_SERIAL);
53 check(server_queue != NULL);
54 });
55
56 return server_queue;
57 }
58
59 static Boolean _processEqualCallBack(const void *value1, const void *value2)
60 {
61 audit_info_s * info1 = (audit_info_s*)value1;
62 audit_info_s * info2 = (audit_info_s*)value2;
63 if (info1->pid == info2->pid) {
64 if (info1->tid == info2->tid) {
65 return true;
66 }
67 }
68 return false;
69 }
70
71 static CFHashCode _processHashCallBack(const void *value)
72 {
73 audit_info_s * info = (audit_info_s*)value;
74 uint64_t crc = crc64_init();
75 crc = crc64_update(crc, &info->pid, sizeof(info->pid));
76 crc = crc64_update(crc, &info->tid, sizeof(info->tid));
77 crc = crc64_final(crc);
78 return (CFHashCode)crc;
79 }
80
81 static const CFDictionaryKeyCallBacks kProcessMapKeyCallBacks = {
82 .version = 0,
83 .retain = NULL,
84 .release = NULL,
85 .copyDescription = NULL,
86 .equal = &_processEqualCallBack,
87 .hash = &_processHashCallBack
88 };
89
90 static Boolean _sessionEqualCallBack(const void *value1, const void *value2)
91 {
92 return (*(session_id_t*)value1) == (*(session_id_t*)value2);
93 }
94
95 static CFHashCode _sessionHashCallBack(const void *value)
96 {
97 return (CFHashCode)(*(session_id_t*)(value));
98 }
99
100 static const CFDictionaryKeyCallBacks kSessionMapKeyCallBacks = {
101 .version = 0,
102 .retain = NULL,
103 .release = NULL,
104 .copyDescription = NULL,
105 .equal = &_sessionEqualCallBack,
106 .hash = &_sessionHashCallBack
107 };
108
109 void server_cleanup()
110 {
111 CFRelease(gProcessMap);
112 CFRelease(gSessionMap);
113 CFRelease(gAuthTokenMap);
114
115 IOPMConnectionSetDispatchQueue(gIOPMconn, NULL);
116 IOPMConnectionRelease(gIOPMconn);
117
118 dispatch_queue_t queue = get_server_dispatch_queue();
119 if (queue) {
120 dispatch_release(queue);
121 }
122 dispatch_release(power_queue);
123 }
124
125 static void _IOMPCallBack(void * param AUTH_UNUSED, IOPMConnection connection, IOPMConnectionMessageToken token, IOPMSystemPowerStateCapabilities capabilities)
126 {
127 os_log_debug(AUTHD_LOG, "server: IOMP powerstates %i", capabilities);
128 if (capabilities & kIOPMSystemPowerStateCapabilityDisk)
129 os_log_debug(AUTHD_LOG, "server: disk");
130 if (capabilities & kIOPMSystemPowerStateCapabilityNetwork)
131 os_log_debug(AUTHD_LOG, "server: net");
132 if (capabilities & kIOPMSystemPowerStateCapabilityAudio)
133 os_log_debug(AUTHD_LOG, "server: audio");
134 if (capabilities & kIOPMSystemPowerStateCapabilityVideo)
135 os_log_debug(AUTHD_LOG, "server: video");
136
137 /* if cpu and no display -> in DarkWake */
138 os_log_debug(AUTHD_LOG, "server: DarkWake check current=%i==%i", (capabilities & (kIOPMSystemPowerStateCapabilityCPU|kIOPMSystemPowerStateCapabilityVideo)), kIOPMSystemPowerStateCapabilityCPU);
139 if ((capabilities & (kIOPMSystemPowerStateCapabilityCPU|kIOPMSystemPowerStateCapabilityVideo)) == kIOPMSystemPowerStateCapabilityCPU) {
140 os_log_debug(AUTHD_LOG, "server: enter DW");
141 gInDarkWake = true;
142 } else if (gInDarkWake) {
143 os_log_debug(AUTHD_LOG, "server: exit DW");
144 gInDarkWake = false;
145 }
146
147 (void)IOPMConnectionAcknowledgeEvent(connection, token);
148
149 return;
150 }
151
152 static void
153 _setupDarkWake(void *__unused ctx)
154 {
155 IOReturn ret;
156
157 IOPMConnectionCreate(CFSTR("IOPowerWatcher"),
158 kIOPMSystemPowerStateCapabilityDisk
159 | kIOPMSystemPowerStateCapabilityNetwork
160 | kIOPMSystemPowerStateCapabilityAudio
161 | kIOPMSystemPowerStateCapabilityVideo,
162 &gIOPMconn);
163
164 ret = IOPMConnectionSetNotification(gIOPMconn, NULL, _IOMPCallBack);
165 if (ret != kIOReturnSuccess)
166 return;
167
168 IOPMConnectionSetDispatchQueue(gIOPMconn, power_queue);
169
170 IOPMScheduleUserActiveChangedNotification(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(bool active) {
171 if (active) {
172 gInDarkWake = false;
173 }
174 });
175 }
176
177 bool server_in_dark_wake()
178 {
179 return gInDarkWake;
180 }
181
182 authdb_t server_get_database()
183 {
184 return gDatabase;
185 }
186
187 static void _setupAuditSessionMonitor()
188 {
189 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
190 au_sdev_handle_t *dev = au_sdev_open(AU_SDEVF_ALLSESSIONS);
191 int event;
192 auditinfo_addr_t aia;
193
194 if (NULL == dev) {
195 os_log_error(AUTHD_LOG, "server: could not open %{public}s %d", AUDIT_SDEV_PATH, errno);
196 return;
197 }
198
199 for (;;) {
200 if (0 != au_sdev_read_aia(dev, &event, &aia)) {
201 os_log_error(AUTHD_LOG, "server: au_sdev_read_aia failed: %d", errno);
202 continue;
203 }
204 os_log_debug(AUTHD_LOG, "server: au_sdev_handle_t event=%i, session=%i", event, aia.ai_asid);
205 if (event == AUE_SESSION_END) {
206 dispatch_async(get_server_dispatch_queue(), ^{
207 os_log_debug(AUTHD_LOG, "server: session %i destroyed", aia.ai_asid);
208 CFDictionaryRemoveValue(gSessionMap, &aia.ai_asid);
209 });
210 }
211 }
212
213 });
214 }
215
216 static void _setupSignalHandlers()
217 {
218 signal(SIGTERM, SIG_IGN);
219 static dispatch_source_t sigtermHandler;
220 sigtermHandler = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, SIGTERM, 0, get_server_dispatch_queue());
221 if (sigtermHandler) {
222 dispatch_source_set_event_handler(sigtermHandler, ^{
223
224 // should we clean up any state?
225 exit(EXIT_SUCCESS);
226 });
227 dispatch_resume(sigtermHandler);
228 }
229 }
230
231 OSStatus server_init(void)
232 {
233 OSStatus status = errAuthorizationSuccess;
234
235 auditinfo_addr_t info;
236 memset(&info, 0, sizeof(info));
237 getaudit_addr(&info, sizeof(info));
238 os_log_debug(AUTHD_LOG, "server: uid=%i, sid=%i", info.ai_auid, info.ai_asid);
239
240 require_action(get_server_dispatch_queue() != NULL, done, status = errAuthorizationInternal);
241
242 gProcessMap = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kProcessMapKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
243 require_action(gProcessMap != NULL, done, status = errAuthorizationInternal);
244
245 gSessionMap = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kSessionMapKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
246 require_action(gSessionMap != NULL, done, status = errAuthorizationInternal);
247
248 gAuthTokenMap = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kAuthTokenKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
249 require_action(gAuthTokenMap != NULL, done, status = errAuthorizationInternal);
250
251 gDatabase = authdb_create();
252 require_action(gDatabase != NULL, done, status = errAuthorizationInternal);
253
254 // check to see if we have an updates
255 authdb_connection_t dbconn = authdb_connection_acquire(gDatabase);
256 authdb_maintenance(dbconn);
257 authdb_connection_release(&dbconn);
258
259 power_queue = dispatch_queue_create("com.apple.security.auth.power", DISPATCH_QUEUE_SERIAL);
260 require_action(power_queue != NULL, done, status = errAuthorizationInternal);
261 dispatch_async_f(power_queue, NULL, _setupDarkWake);
262
263 _setupAuditSessionMonitor();
264 _setupSignalHandlers();
265
266 done:
267 return status;
268 }
269
270 static void _server_parse_audit_token(audit_token_t * token, audit_info_s * info)
271 {
272 if (token && info) {
273 memset(info, 0, sizeof(*info));
274 au_tid_t tid;
275 memset(&tid, 0, sizeof(tid));
276 audit_token_to_au32(*token, &info->auid, &info->euid,
277 &info->egid, &info->ruid, &info->rgid,
278 &info->pid, &info->asid, &tid);
279 info->tid = tid.port;
280 info->opaqueToken = *token;
281 }
282 }
283
284 connection_t
285 server_register_connection(xpc_connection_t connection)
286 {
287 __block connection_t conn = NULL;
288 __block session_t session = NULL;
289 __block process_t proc = NULL;
290 __block CFIndex conn_count = 0;
291
292 require(connection != NULL, done);
293
294 audit_token_t auditToken;
295 audit_info_s info;
296 xpc_connection_get_audit_token(connection, &auditToken);
297 _server_parse_audit_token(&auditToken, &info);
298
299
300 dispatch_sync(get_server_dispatch_queue(), ^{
301 session = (session_t)CFDictionaryGetValue(gSessionMap, &info.asid);
302 if (session) {
303 CFRetain(session);
304 } else {
305 session = session_create(info.asid);
306 CFDictionarySetValue(gSessionMap, session_get_key(session), session);
307 }
308
309 proc = (process_t)CFDictionaryGetValue(gProcessMap, &info);
310 if (proc) {
311 CFRetain(proc);
312 }
313
314 if (proc) {
315 conn = connection_create(proc);
316 conn_count = process_add_connection(proc, conn);
317 } else {
318 proc = process_create(&info, session);
319 if (proc) {
320 conn = connection_create(proc);
321 conn_count = process_add_connection(proc, conn);
322 session_add_process(session, proc);
323 CFDictionarySetValue(gProcessMap, process_get_key(proc), proc);
324 }
325 }
326
327 if (!gXPCTransaction) {
328 xpc_transaction_begin();
329 gXPCTransaction = true;
330 }
331 });
332
333 os_log_debug(AUTHD_LOG, "server: registered connection (total=%li)", conn_count);
334
335 done:
336 CFReleaseSafe(session);
337 CFReleaseSafe(proc);
338 return conn;
339 }
340
341 void
342 server_unregister_connection(connection_t conn)
343 {
344 assert(conn); // marked non-null
345 process_t proc = connection_get_process(conn);
346
347 dispatch_sync(get_server_dispatch_queue(), ^{
348 CFIndex connectionCount = process_get_connection_count(proc);
349 os_log_debug(AUTHD_LOG, "server: unregistered connection (total=%li)", connectionCount);
350
351 if (connectionCount == 1) {
352 CFDictionaryRemoveValue(gProcessMap, process_get_key(proc));
353 }
354
355 if (CFDictionaryGetCount(gProcessMap) == 0) {
356 xpc_transaction_end();
357 gXPCTransaction = false;
358 }
359 });
360 // move the destruction of the connection/process off the server queue
361 CFRelease(conn);
362 }
363
364 void
365 server_register_auth_token(auth_token_t auth)
366 {
367 assert(auth); // marked non-null
368 dispatch_sync(get_server_dispatch_queue(), ^{
369 os_log_debug(AUTHD_LOG, "server: registering authorization");
370 CFDictionarySetValue(gAuthTokenMap, auth_token_get_key(auth), auth);
371 auth_token_set_state(auth, auth_token_state_registered);
372 });
373 }
374
375 void
376 server_unregister_auth_token(auth_token_t auth)
377 {
378 assert(auth);
379 AuthorizationBlob blob = *(AuthorizationBlob*)auth_token_get_key(auth);
380 dispatch_async(get_server_dispatch_queue(), ^{
381 os_log_debug(AUTHD_LOG, "server: unregistering authorization");
382 CFDictionaryRemoveValue(gAuthTokenMap, &blob);
383 });
384 }
385
386 auth_token_t
387 server_find_copy_auth_token(AuthorizationBlob * blob)
388 {
389 assert(blob); // marked non-null
390 __block auth_token_t auth = NULL;
391 dispatch_sync(get_server_dispatch_queue(), ^{
392 auth = (auth_token_t)CFDictionaryGetValue(gAuthTokenMap, blob);
393 if (auth) {
394 CFRetain(auth);
395 }
396 });
397 return auth;
398 }
399
400 session_t
401 server_find_copy_session(session_id_t sid, bool create)
402 {
403 __block session_t session = NULL;
404
405 dispatch_sync(get_server_dispatch_queue(), ^{
406 session = (session_t)CFDictionaryGetValue(gSessionMap, &sid);
407 if (session) {
408 CFRetain(session);
409 } else if (create) {
410 session = session_create(sid);
411 if (session) {
412 CFDictionarySetValue(gSessionMap, session_get_key(session), session);
413 }
414 }
415 });
416
417 return session;
418 }
419
420 #pragma mark -
421 #pragma mark API
422
423 static OSStatus
424 _process_find_copy_auth_token_from_xpc(process_t proc, xpc_object_t message, auth_token_t * auth_out)
425 {
426 OSStatus status = errAuthorizationSuccess;
427 require_action(auth_out != NULL, done, status = errAuthorizationInternal);
428
429 size_t len;
430 AuthorizationBlob * blob = (AuthorizationBlob *)xpc_dictionary_get_data(message, AUTH_XPC_BLOB, &len);
431 require_action(blob != NULL, done, status = errAuthorizationInvalidRef);
432 require_action(len == sizeof(AuthorizationBlob), done, status = errAuthorizationInvalidRef);
433
434 auth_token_t auth = process_find_copy_auth_token(proc, blob);
435 require_action(auth != NULL, done, status = errAuthorizationInvalidRef);
436
437 #if DEBUG
438 os_log_debug(AUTHD_LOG, "server: authtoken lookup %#x%x %p", blob->data[1],blob->data[0], auth);
439 #else
440 os_log_debug(AUTHD_LOG, "server: authtoken lookup");
441 #endif
442
443 *auth_out = auth;
444
445 done:
446 return status;
447 }
448
449 static OSStatus _server_preauthorize(connection_t conn, auth_token_t auth, auth_items_t context, engine_t * engine_out)
450 {
451 __block OSStatus status = errAuthorizationDenied;
452 engine_t engine = NULL;
453
454 require_action(conn, done, status = errAuthorizationInternal);
455
456 engine = engine_create(conn, auth);
457 require_action(engine, done, status = errAuthorizationInternal);
458
459 status = engine_preauthorize(engine, context);
460
461 done:
462 if (engine) {
463 if (engine_out) {
464 *engine_out = engine;
465 } else {
466 CFRelease(engine);
467 }
468 }
469 return status;
470 }
471
472 static OSStatus _server_authorize(connection_t conn, auth_token_t auth, AuthorizationFlags flags, auth_rights_t rights, auth_items_t environment, engine_t * engine_out)
473 {
474 __block OSStatus status = errAuthorizationDenied;
475 engine_t engine = NULL;
476
477 require_action(conn, done, status = errAuthorizationInternal);
478
479 engine = engine_create(conn, auth);
480 require_action(engine, done, status = errAuthorizationInternal);
481
482 if (flags & kAuthorizationFlagInteractionAllowed) {
483 dispatch_sync(connection_get_dispatch_queue(conn), ^{
484 connection_set_engine(conn, engine);
485 status = engine_authorize(engine, rights, environment, flags);
486 connection_set_engine(conn, NULL);
487 });
488 } else {
489 status = engine_authorize(engine, rights, environment, flags);
490 }
491
492 done:
493 if (engine) {
494 if (engine_out) {
495 *engine_out = engine;
496 } else {
497 CFRelease(engine);
498 }
499 }
500 return status;
501 }
502
503 // IN: AUTH_XPC_RIGHTS, AUTH_XPC_ENVIRONMENT, AUTH_XPC_FLAGS
504 // OUT: AUTH_XPC_BLOB
505 OSStatus
506 authorization_create(connection_t conn, xpc_object_t message, xpc_object_t reply)
507 {
508 OSStatus status = errAuthorizationDenied;
509
510 process_t proc = connection_get_process(conn);
511
512 // Passed in args
513 auth_rights_t rights = auth_rights_create_with_xpc(xpc_dictionary_get_value(message, AUTH_XPC_RIGHTS));
514 auth_items_t environment = auth_items_create_with_xpc(xpc_dictionary_get_value(message, AUTH_XPC_ENVIRONMENT));
515 AuthorizationFlags flags = (AuthorizationFlags)xpc_dictionary_get_uint64(message, AUTH_XPC_FLAGS);
516
517 // Create Authorization Token
518 auth_token_t auth = auth_token_create(proc, flags & kAuthorizationFlagLeastPrivileged);
519 require_action(auth != NULL, done, status = errAuthorizationInternal);
520
521 if (!(flags & kAuthorizationFlagNoData)) {
522 process_add_auth_token(proc,auth);
523 }
524
525 status = _server_authorize(conn, auth, flags, rights, environment, NULL);
526 require_noerr(status, done);
527
528 //reply
529 xpc_dictionary_set_data(reply, AUTH_XPC_BLOB, auth_token_get_blob(auth), sizeof(AuthorizationBlob));
530
531 done:
532 CFReleaseSafe(rights);
533 CFReleaseSafe(environment);
534 CFReleaseSafe(auth);
535 return status;
536 }
537
538 // IN: AUTH_XPC_DATA, AUTH_XPC_ENVIRONMENT, AUTH_XPC_FLAGS
539 // OUT: AUTH_XPC_BLOB
540 OSStatus authorization_create_with_audit_token(connection_t conn, xpc_object_t message, xpc_object_t reply)
541 {
542 OSStatus status = errAuthorizationDenied;
543 auth_token_t auth = NULL;
544
545 process_t proc = connection_get_process(conn);
546 require(process_get_uid(proc) == 0, done); //only root can use this call
547
548 // Passed in args
549 size_t len = 0;
550 const char * data = xpc_dictionary_get_data(message, AUTH_XPC_DATA, &len);
551 require(data != NULL, done);
552 require(len == sizeof(audit_token_t), done);
553
554 // auth_items_t environment = auth_items_create_with_xpc(xpc_dictionary_get_value(message, AUTH_XPC_ENVIRONMENT));
555 AuthorizationFlags flags = (AuthorizationFlags)xpc_dictionary_get_uint64(message, AUTH_XPC_FLAGS);
556
557 audit_info_s auditInfo;
558 _server_parse_audit_token((audit_token_t*)data, &auditInfo);
559
560 // Create Authorization Token
561 auth = auth_token_create(proc, flags & kAuthorizationFlagLeastPrivileged);
562 require_action(auth != NULL, done, status = errAuthorizationInternal);
563
564 process_add_auth_token(proc,auth);
565
566 //reply
567 xpc_dictionary_set_data(reply, AUTH_XPC_BLOB, auth_token_get_blob(auth), sizeof(AuthorizationBlob));
568
569 done:
570 // CFReleaseSafe(environment);
571 CFReleaseSafe(auth);
572 return status;
573 }
574
575 // IN: AUTH_XPC_BLOB, AUTH_XPC_FLAGS
576 // OUT:
577 OSStatus
578 authorization_free(connection_t conn, xpc_object_t message, xpc_object_t reply AUTH_UNUSED)
579 {
580 OSStatus status = errAuthorizationSuccess;
581 AuthorizationFlags flags = 0;
582 process_t proc = connection_get_process(conn);
583
584 auth_token_t auth = NULL;
585 status = _process_find_copy_auth_token_from_xpc(proc, message, &auth);
586 require_noerr(status, done);
587
588 flags = (AuthorizationFlags)xpc_dictionary_get_uint64(message, AUTH_XPC_FLAGS);
589
590 if (flags & kAuthorizationFlagDestroyRights) {
591 auth_token_credentials_iterate(auth, ^bool(credential_t cred) {
592 credential_invalidate(cred);
593 os_log_debug(AUTHD_LOG, "engine[%i]: invalidating %{public}scredential %{public}s (%i)", connection_get_pid(conn), credential_get_shared(cred) ? "shared " : "", credential_get_name(cred), credential_get_uid(cred));
594 return true;
595 });
596
597 session_credentials_purge(auth_token_get_session(auth));
598 }
599
600 process_remove_auth_token(proc, auth, flags);
601
602 done:
603 CFReleaseSafe(auth);
604 os_log_debug(AUTHD_LOG, "server: AuthorizationFree %d (flags:%x)", (int)status, (unsigned int)flags);
605 return status;
606 }
607
608 // IN: AUTH_XPC_BLOB, AUTH_XPC_DATA
609 // OUT:
610 OSStatus
611 authorization_preauthorize_credentials(connection_t conn, xpc_object_t message, xpc_object_t reply)
612 {
613 OSStatus status = errAuthorizationDenied;
614 engine_t engine = NULL;
615
616 process_t proc = connection_get_process(conn);
617
618 // Passed in args
619 auth_items_t context = auth_items_create_with_xpc(xpc_dictionary_get_value(message, AUTH_XPC_DATA));
620
621 auth_token_t auth = NULL;
622 status = _process_find_copy_auth_token_from_xpc(proc, message, &auth);
623 require_noerr_action_quiet(status, done, os_log_error(AUTHD_LOG, "preauthorize_credentials: no auth token"));
624
625 status = _server_preauthorize(conn, auth, context, &engine);
626 require_noerr_action_quiet(status, done, os_log_error(AUTHD_LOG, "preauthorize_credentials: authorization failed"));
627
628 done:
629 CFReleaseSafe(context);
630 CFReleaseSafe(auth);
631 CFReleaseSafe(engine);
632
633 return status;
634 }
635
636
637 // IN: AUTH_XPC_BLOB, AUTH_XPC_RIGHTS, AUTH_XPC_ENVIRONMENT, AUTH_XPC_FLAGS
638 // OUT: AUTH_XPC_OUT_ITEMS
639 OSStatus
640 authorization_copy_rights(connection_t conn, xpc_object_t message, xpc_object_t reply)
641 {
642 OSStatus status = errAuthorizationDenied;
643 engine_t engine = NULL;
644
645 process_t proc = connection_get_process(conn);
646
647 // Passed in args
648 auth_rights_t rights = auth_rights_create_with_xpc(xpc_dictionary_get_value(message, AUTH_XPC_RIGHTS));
649 auth_items_t environment = auth_items_create_with_xpc(xpc_dictionary_get_value(message, AUTH_XPC_ENVIRONMENT));
650 AuthorizationFlags flags = (AuthorizationFlags)xpc_dictionary_get_uint64(message, AUTH_XPC_FLAGS);
651
652 auth_token_t auth = NULL;
653 status = _process_find_copy_auth_token_from_xpc(proc, message, &auth);
654 require_noerr_action_quiet(status, done, os_log_error(AUTHD_LOG, "copy_rights: no auth token"));
655
656 status = _server_authorize(conn, auth, flags, rights, environment, &engine);
657 require_noerr_action_quiet(status, done, os_log_error(AUTHD_LOG, "copy_rights: authorization failed"));
658
659 //reply
660 xpc_object_t outItems = auth_rights_export_xpc(engine_get_granted_rights(engine));
661 xpc_dictionary_set_value(reply, AUTH_XPC_OUT_ITEMS, outItems);
662 xpc_release_safe(outItems);
663
664 done:
665 CFReleaseSafe(rights);
666 CFReleaseSafe(environment);
667 CFReleaseSafe(auth);
668 CFReleaseSafe(engine);
669
670 return status;
671 }
672
673 // IN: AUTH_XPC_BLOB, AUTH_XPC_TAG
674 // OUT: AUTH_XPC_OUT_ITEMS
675 OSStatus
676 authorization_copy_info(connection_t conn, xpc_object_t message, xpc_object_t reply)
677 {
678
679 OSStatus status = errAuthorizationSuccess;
680 auth_items_t items = NULL;
681 auth_items_t local_items = NULL;
682 const char * tag = NULL;
683
684 process_t proc = connection_get_process(conn);
685
686 auth_token_t auth = NULL;
687 status = _process_find_copy_auth_token_from_xpc(proc, message, &auth);
688 require_noerr_action_quiet(status, done, os_log_error(AUTHD_LOG, "copy_info: no auth token"));
689
690 items = auth_items_create();
691
692 tag = xpc_dictionary_get_string(message, AUTH_XPC_TAG);
693 os_log_debug(AUTHD_LOG, "server: requested tag: %{public}s", tag ? tag : "(all)");
694 if (tag) {
695 size_t len;
696 const void * data = auth_items_get_data_with_flags(auth_token_get_context(auth), tag, &len, kAuthorizationContextFlagExtractable);
697 if (data) {
698 os_log_debug(AUTHD_LOG, "server: requested tag found");
699 auth_items_set_data(items, tag, data, len);
700 }
701 } else {
702 auth_items_copy_with_flags(items, auth_token_get_context(auth), kAuthorizationContextFlagExtractable);
703 }
704
705 local_items = auth_items_create();
706 auth_items_content_copy(local_items, items); // we do not want decrypt content of the authorizationref memory which is where pointers point to
707 auth_items_decrypt(local_items, auth_token_get_encryption_key(auth));
708 os_log_debug(AUTHD_LOG, "server: decrypted authorization context data");
709
710 #if DEBUG
711 os_log_debug(AUTHD_LOG, "server: Dumping requested AuthRef items: %{public}@", items);
712 #endif
713
714 //reply
715 xpc_object_t outItems = auth_items_export_xpc(local_items);
716 xpc_dictionary_set_value(reply, AUTH_XPC_OUT_ITEMS, outItems);
717 xpc_release_safe(outItems);
718
719 done:
720 CFReleaseSafe(local_items);
721 CFReleaseSafe(items);
722 CFReleaseSafe(auth);
723 os_log_debug(AUTHD_LOG, "server: AuthorizationCopyInfo %i", (int) status);
724 return status;
725 }
726
727 // IN: AUTH_XPC_BLOB
728 // OUT: AUTH_XPC_EXTERNAL
729 OSStatus
730 authorization_make_external_form(connection_t conn, xpc_object_t message, xpc_object_t reply)
731 {
732 OSStatus status = errAuthorizationSuccess;
733
734 process_t proc = connection_get_process(conn);
735
736 auth_token_t auth = NULL;
737 status = _process_find_copy_auth_token_from_xpc(proc, message, &auth);
738 require_noerr(status, done);
739
740 AuthorizationExternalForm exForm;
741 AuthorizationExternalBlob * exBlob = (AuthorizationExternalBlob *)&exForm;
742 memset(&exForm, 0, sizeof(exForm));
743
744 exBlob->blob = *auth_token_get_blob(auth);
745 exBlob->session = process_get_session_id(proc);
746
747 xpc_dictionary_set_data(reply, AUTH_XPC_EXTERNAL, &exForm, sizeof(exForm));
748 server_register_auth_token(auth);
749
750 done:
751 CFReleaseSafe(auth);
752 os_log_debug(AUTHD_LOG, "server: AuthorizationMakeExternalForm %d", (int)status);
753 return status;
754 }
755
756 // IN: AUTH_XPC_EXTERNAL
757 // OUT: AUTH_XPC_BLOB
758 OSStatus
759 authorization_create_from_external_form(connection_t conn, xpc_object_t message, xpc_object_t reply)
760 {
761 OSStatus status = errAuthorizationSuccess;
762 auth_token_t auth = NULL;
763
764 process_t proc = connection_get_process(conn);
765
766 size_t len;
767 AuthorizationExternalForm * exForm = (AuthorizationExternalForm *)xpc_dictionary_get_data(message, AUTH_XPC_EXTERNAL, &len);
768 require_action(exForm != NULL, done, status = errAuthorizationInternal);
769 require_action(len == sizeof(AuthorizationExternalForm), done, status = errAuthorizationInvalidRef);
770
771 AuthorizationExternalBlob * exBlob = (AuthorizationExternalBlob *)exForm;
772 auth = server_find_copy_auth_token(&exBlob->blob);
773 require_action(auth != NULL, done, status = errAuthorizationDenied);
774
775 process_add_auth_token(proc, auth);
776 xpc_dictionary_set_data(reply, AUTH_XPC_BLOB, auth_token_get_blob(auth), sizeof(AuthorizationBlob));
777
778 done:
779 CFReleaseSafe(auth);
780 os_log_debug(AUTHD_LOG, "server: AuthorizationCreateFromExternalForm %d", (int)status);
781 return status;
782 }
783
784 // IN: AUTH_XPC_RIGHT_NAME
785 // OUT: AUTH_XPC_DATA
786 OSStatus
787 authorization_right_get(connection_t conn AUTH_UNUSED, xpc_object_t message, xpc_object_t reply)
788 {
789 OSStatus status = errAuthorizationDenied;
790 rule_t rule = NULL;
791 CFTypeRef cfdict = NULL;
792 xpc_object_t xpcdict = NULL;
793
794 authdb_connection_t dbconn = authdb_connection_acquire(server_get_database());
795 rule = rule_create_with_string(xpc_dictionary_get_string(message, AUTH_XPC_RIGHT_NAME), dbconn);
796 require(rule != NULL, done);
797 require(rule_get_id(rule) != 0, done);
798
799 cfdict = rule_copy_to_cfobject(rule, dbconn);
800 require(cfdict != NULL, done);
801
802 xpcdict = _CFXPCCreateXPCObjectFromCFObject(cfdict);
803 require(xpcdict != NULL, done);
804
805 // reply
806 xpc_dictionary_set_value(reply, AUTH_XPC_DATA, xpcdict);
807
808 status = errAuthorizationSuccess;
809
810 done:
811 authdb_connection_release(&dbconn);
812 CFReleaseSafe(cfdict);
813 xpc_release_safe(xpcdict);
814 CFReleaseSafe(rule);
815 os_log_debug(AUTHD_LOG, "server: AuthorizationRightGet %d", (int)status);
816 return status;
817 }
818
819 static bool _prompt_for_modifications(process_t __unused proc, rule_t __unused rule)
820 {
821 // <rdar://problem/13853228> will put back it back at some later date
822 // SecRequirementRef ruleReq = rule_get_requirement(rule);
823 //
824 // if (ruleReq && process_verify_requirment(proc, ruleReq)) {
825 // return false;
826 // }
827
828 return true;
829 }
830
831 static CFIndex _get_mechanism_index(CFArrayRef mechanisms, CFStringRef m_name)
832 {
833 CFIndex index = -1;
834 require(mechanisms, done);
835
836 CFIndex c = CFArrayGetCount(mechanisms);
837 CFStringRef i_name = NULL;
838 for (CFIndex i = 0; i < c; ++i)
839 {
840 i_name = CFArrayGetValueAtIndex(mechanisms, i);
841 if (i_name && (CFGetTypeID(m_name) == CFStringGetTypeID())) {
842 if (CFStringCompare(i_name, m_name, kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
843 index = i;
844 break;
845 }
846 }
847 }
848
849 done:
850 return index;
851 }
852
853 static bool _update_rule_mechanism(authdb_connection_t dbconn, const char * rule_name, CFStringRef mechanism_name, CFStringRef insert_after_name, bool remove)
854 {
855 bool updated = false;
856 rule_t rule = NULL;
857 rule_t update_rule = NULL;
858 CFMutableDictionaryRef cfdict = NULL;
859 CFStringRef update_name = NULL;
860
861 require(mechanism_name, done);
862
863 rule = rule_create_with_string(rule_name, dbconn);
864 require(rule_get_id(rule) != 0, done); // rule doesn't exist in the database
865
866 cfdict = rule_copy_to_cfobject(rule, dbconn);
867 require(cfdict != NULL, done);
868
869 CFMutableArrayRef mechanisms = NULL;
870 bool res = CFDictionaryGetValueIfPresent(cfdict, CFSTR(kAuthorizationRuleParameterMechanisms), (void*)&mechanisms);
871 require(res == true, done);
872
873 CFIndex index = -1;
874
875 if (remove) {
876 index = _get_mechanism_index(mechanisms, mechanism_name);
877 } else {
878 if (insert_after_name) {
879 if ((index = _get_mechanism_index(mechanisms, insert_after_name)) != -1) {
880 index++;
881 } else {
882 index = 0; // if we couldn't find the index add it to the begining
883 }
884 } else {
885 index = 0;
886 }
887 }
888
889 if (index != -1) {
890 if(remove) {
891 CFArrayRemoveValueAtIndex(mechanisms, index);
892 } else {
893 if (index < CFArrayGetCount(mechanisms)) {
894 require_action(CFStringCompare(CFArrayGetValueAtIndex(mechanisms, index), mechanism_name, kCFCompareCaseInsensitive) != kCFCompareEqualTo, done, updated = true);
895 }
896 CFArrayInsertValueAtIndex(mechanisms, index, mechanism_name);
897 }
898
899 CFDictionarySetValue(cfdict, CFSTR(kAuthorizationRuleParameterMechanisms), mechanisms);
900
901 // and write it back
902 update_name = CFStringCreateWithCString(kCFAllocatorDefault, rule_name, kCFStringEncodingUTF8);
903 require(update_name, done);
904 update_rule = rule_create_with_plist(rule_get_type(rule), update_name, cfdict, dbconn);
905 require(update_rule, done);
906
907 require(rule_sql_commit(update_rule, dbconn, CFAbsoluteTimeGetCurrent(), NULL), done);
908 }
909
910 updated = true;
911
912 done:
913 CFReleaseSafe(rule);
914 CFReleaseSafe(update_rule);
915 CFReleaseSafe(cfdict);
916 CFReleaseSafe(update_name);
917 return updated;
918 }
919
920 /// IN: AUTH_XPC_BLOB, AUTH_XPC_INT64
921 // OUT:
922 OSStatus
923 authorization_enable_smartcard(connection_t conn, xpc_object_t message, xpc_object_t reply AUTH_UNUSED)
924 {
925 const CFStringRef SMARTCARD_LINE = CFSTR("builtin:smartcard-sniffer,privileged");
926 const CFStringRef BUILTIN_LINE = CFSTR("builtin:policy-banner");
927 const char* SYSTEM_LOGIN_CONSOLE = "system.login.console";
928 const char* AUTHENTICATE = "authenticate";
929
930 __block OSStatus status = errAuthorizationSuccess;
931 bool enable_smartcard = false;
932 authdb_connection_t dbconn = NULL;
933 auth_token_t auth = NULL;
934 auth_rights_t checkRight = NULL;
935
936 process_t proc = connection_get_process(conn);
937
938 status = _process_find_copy_auth_token_from_xpc(proc, message, &auth);
939 require_noerr(status, done);
940
941 checkRight = auth_rights_create();
942 auth_rights_add(checkRight, "config.modify.smartcard");
943 status = _server_authorize(conn, auth, kAuthorizationFlagDefaults | kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights, checkRight, NULL, NULL);
944 require_noerr(status, done);
945
946 enable_smartcard = xpc_dictionary_get_bool(message, AUTH_XPC_DATA);
947
948 dbconn = authdb_connection_acquire(server_get_database());
949
950 if (!_update_rule_mechanism(dbconn, SYSTEM_LOGIN_CONSOLE, SMARTCARD_LINE, BUILTIN_LINE, enable_smartcard ? false : true)) {
951 status = errAuthorizationInternal;
952 os_log_error(AUTHD_LOG, "server: smartcard: enable(%i) failed to update %{public}s", enable_smartcard, SYSTEM_LOGIN_CONSOLE);
953 }
954 if (!_update_rule_mechanism(dbconn, AUTHENTICATE, SMARTCARD_LINE, NULL, enable_smartcard ? false : true)) {
955 status = errAuthorizationInternal;
956 os_log_error(AUTHD_LOG, "server: smartcard: enable(%i) failed to update %{public}s", enable_smartcard, AUTHENTICATE);
957 }
958
959 authdb_checkpoint(dbconn);
960
961 done:
962 authdb_connection_release(&dbconn);
963 CFReleaseSafe(checkRight);
964 CFReleaseSafe(auth);
965 return status;
966 }
967
968 static int64_t _process_get_identifier_count(process_t proc, authdb_connection_t conn)
969 {
970 __block int64_t result = 0;
971
972 authdb_step(conn, "SELECT COUNT(*) AS cnt FROM rules WHERE identifier = ? ", ^(sqlite3_stmt *stmt) {
973 sqlite3_bind_text(stmt, 1, process_get_identifier(proc), -1, NULL);
974 }, ^bool(auth_items_t data) {
975 result = auth_items_get_int64(data, "cnt");
976 return true;
977 });
978
979 return result;
980 }
981
982 static int64_t _get_max_process_rights()
983 {
984 static dispatch_once_t onceToken;
985 static int64_t max_rights = MAX_PROCESS_RIGHTS;
986
987 //sudo defaults write /Library/Preferences/com.apple.authd max_process_rights -bool true
988 dispatch_once(&onceToken, ^{
989 CFTypeRef max = (CFNumberRef)CFPreferencesCopyValue(CFSTR("max_process_rights"), CFSTR(SECURITY_AUTH_NAME), kCFPreferencesAnyUser, kCFPreferencesCurrentHost);
990
991 if (max && CFGetTypeID(max) == CFNumberGetTypeID()) {
992 CFNumberGetValue(max, kCFNumberSInt64Type, &max_rights);
993 }
994 CFReleaseSafe(max);
995 });
996
997 return max_rights;
998 }
999
1000 // IN: AUTH_XPC_BLOB, AUTH_XPC_RIGHT_NAME, AUTH_XPC_DATA
1001 // OUT:
1002 OSStatus
1003 authorization_right_set(connection_t conn, xpc_object_t message, xpc_object_t reply AUTH_UNUSED)
1004 {
1005 __block OSStatus status = errAuthorizationDenied;
1006 __block engine_t engine = NULL;
1007 CFStringRef cf_rule_name = NULL;
1008 CFDictionaryRef cf_rule_dict = NULL;
1009 rule_t rule = NULL;
1010 rule_t existingRule = NULL;
1011 authdb_connection_t dbconn = NULL;
1012 auth_token_t auth = NULL;
1013 bool force_modify = false;
1014 RuleType rule_type = RT_RIGHT;
1015 const char * rule_name = NULL;
1016 bool auth_rule = false;
1017
1018 process_t proc = connection_get_process(conn);
1019
1020 status = _process_find_copy_auth_token_from_xpc(proc, message, &auth);
1021 require_noerr(status, done);
1022
1023 require_action(xpc_dictionary_get_string(message, AUTH_XPC_RIGHT_NAME) != NULL, done, status = errAuthorizationInternal);
1024 require_action(xpc_dictionary_get_value(message, AUTH_XPC_DATA) != NULL, done, status = errAuthorizationInternal);
1025
1026 rule_name = xpc_dictionary_get_string(message, AUTH_XPC_RIGHT_NAME);
1027 require(rule_name != NULL, done);
1028
1029 if (_compare_string(rule_name, "authenticate")) {
1030 rule_type = RT_RULE;
1031 auth_rule = true;
1032 }
1033
1034 cf_rule_name = CFStringCreateWithCString(kCFAllocatorDefault, rule_name, kCFStringEncodingUTF8);
1035 require(cf_rule_name != NULL, done);
1036
1037 cf_rule_dict = _CFXPCCreateCFObjectFromXPCObject(xpc_dictionary_get_value(message, AUTH_XPC_DATA));
1038 require(cf_rule_dict != NULL, done);
1039
1040 dbconn = authdb_connection_acquire(server_get_database());
1041
1042 rule = rule_create_with_plist(rule_type, cf_rule_name, cf_rule_dict, dbconn);
1043 if (process_get_uid(proc) != 0) {
1044 require_action(rule_get_extract_password(rule) == false, done, status = errAuthorizationDenied; os_log_error(AUTHD_LOG, "server: AuthorizationRightSet not allowed to set extract-password. (denied)"));
1045 }
1046
1047 // if rule doesn't currently exist then we have to check to see if they are over the Max.
1048 if (rule_get_id(rule) == 0) {
1049 if (process_get_identifier(proc) == NULL) {
1050 os_log_error(AUTHD_LOG, "server: AuthorizationRightSet required for process %{public}s (missing code signature). To add rights to the Authorization database, your process must have a code signature.", process_get_code_url(proc));
1051 force_modify = true;
1052 } else {
1053 int64_t process_rule_count = _process_get_identifier_count(proc, dbconn);
1054 if ((process_rule_count >= _get_max_process_rights())) {
1055 if (!connection_get_syslog_warn(conn)) {
1056 os_log_error(AUTHD_LOG, "server: AuthorizationRightSet Denied API abuse process %{public}s already contains %lli rights.", process_get_code_url(proc), _get_max_process_rights());
1057 connection_set_syslog_warn(conn);
1058 }
1059 status = errAuthorizationDenied;
1060 goto done;
1061 }
1062 }
1063 } else {
1064 if (auth_rule) {
1065 if (process_get_uid(proc) != 0) {
1066 os_log_error(AUTHD_LOG, "server: AuthorizationRightSet denied, root required to update the 'authenticate' rule");
1067 status = errAuthorizationDenied;
1068 goto done;
1069 }
1070 } else {
1071 // verify they are updating a right and not a rule
1072 existingRule = rule_create_with_string(rule_get_name(rule), dbconn);
1073 if (rule_get_type(existingRule) == RT_RULE) {
1074 os_log_error(AUTHD_LOG, "server: AuthorizationRightSet Denied updating '%{public}s' rule is prohibited", rule_get_name(existingRule));
1075 status = errAuthorizationDenied;
1076 goto done;
1077 }
1078 }
1079 }
1080
1081 if (_prompt_for_modifications(proc,rule)) {
1082 authdb_connection_release(&dbconn);
1083
1084 dispatch_sync(connection_get_dispatch_queue(conn), ^{
1085 engine = engine_create(conn, auth);
1086 connection_set_engine(conn, engine);
1087 status = engine_verify_modification(engine, rule, false, force_modify);
1088 connection_set_engine(conn, NULL);
1089 });
1090 require_noerr(status, done);
1091
1092 dbconn = authdb_connection_acquire(server_get_database());
1093 }
1094
1095 if (rule_sql_commit(rule, dbconn, engine ? engine_get_time(engine) : CFAbsoluteTimeGetCurrent(), proc)) {
1096 os_log_debug(AUTHD_LOG, "server: Successfully updated rule %{public}s", rule_get_name(rule));
1097 authdb_checkpoint(dbconn);
1098 status = errAuthorizationSuccess;
1099 } else {
1100 os_log_error(AUTHD_LOG, "server: Failed to update rule %{public}s", rule_get_name(rule));
1101 status = errAuthorizationDenied;
1102 }
1103
1104 done:
1105 authdb_connection_release(&dbconn);
1106 CFReleaseSafe(existingRule);
1107 CFReleaseSafe(cf_rule_name);
1108 CFReleaseSafe(cf_rule_dict);
1109 CFReleaseSafe(auth);
1110 CFReleaseSafe(rule);
1111 CFReleaseSafe(engine);
1112 return status;
1113 }
1114
1115 // IN: AUTH_XPC_BLOB, AUTH_XPC_RIGHT_NAME
1116 // OUT:
1117 OSStatus
1118 authorization_right_remove(connection_t conn, xpc_object_t message, xpc_object_t reply AUTH_UNUSED)
1119 {
1120 __block OSStatus status = errAuthorizationDenied;
1121 __block engine_t engine = NULL;
1122 rule_t rule = NULL;
1123 authdb_connection_t dbconn = NULL;
1124
1125 process_t proc = connection_get_process(conn);
1126
1127 auth_token_t auth = NULL;
1128 status = _process_find_copy_auth_token_from_xpc(proc, message, &auth);
1129 require_noerr(status, done);
1130
1131 dbconn = authdb_connection_acquire(server_get_database());
1132
1133 rule = rule_create_with_string(xpc_dictionary_get_string(message, AUTH_XPC_RIGHT_NAME), dbconn);
1134 require(rule != NULL, done);
1135
1136 if (_prompt_for_modifications(proc,rule)) {
1137 authdb_connection_release(&dbconn);
1138
1139 dispatch_sync(connection_get_dispatch_queue(conn), ^{
1140 engine = engine_create(conn, auth);
1141 connection_set_engine(conn, engine);
1142 status = engine_verify_modification(engine, rule, true, false);
1143 connection_set_engine(conn, NULL);
1144 });
1145 require_noerr(status, done);
1146
1147 dbconn = authdb_connection_acquire(server_get_database());
1148 }
1149
1150 if (rule_get_id(rule) != 0) {
1151 rule_sql_remove(rule, dbconn, proc);
1152 }
1153
1154 done:
1155 authdb_connection_release(&dbconn);
1156 CFReleaseSafe(auth);
1157 CFReleaseSafe(rule);
1158 CFReleaseSafe(engine);
1159 os_log_debug(AUTHD_LOG, "server: AuthorizationRightRemove %d", (int)status);
1160 return status;
1161 }
1162
1163 #pragma mark -
1164 #pragma mark test code
1165
1166 OSStatus
1167 session_set_user_preferences(connection_t conn, xpc_object_t message, xpc_object_t reply)
1168 {
1169 (void)conn;
1170 (void)message;
1171 (void)reply;
1172 return errAuthorizationSuccess;
1173 }
1174
1175 void
1176 server_dev() {
1177 // rule_t rule = rule_create_with_string("system.preferences.accounts");
1178 // CFDictionaryRef dict = rule_copy_to_cfobject(rule);
1179 // _show_cf(dict);
1180 // CFReleaseSafe(rule);
1181 // CFReleaseSafe(dict);
1182
1183 // auth_items_t config = NULL;
1184 // double d2 = 0, d1 = 5;
1185 // authdb_get_key_value(server_get_authdb_reader(), "config", &config);
1186 // auth_items_set_double(config, "test", d1);
1187 // d2 = auth_items_get_double(config, "test");
1188 // os_log_debug(AUTHD_LOG, "d1=%f d2=%f", d1, d2);
1189 // CFReleaseSafe(config);
1190
1191
1192 // auth_items_t items = auth_items_create();
1193 // auth_items_set_string(items, "test", "testing 1");
1194 // auth_items_set_string(items, "test2", "testing 2");
1195 // auth_items_set_string(items, "test3", "testing 3");
1196 // auth_items_set_flags(items, "test3", 4);
1197 // auth_items_set_string(items, "apple", "apple");
1198 // auth_items_set_flags(items, "apple", 1);
1199 // auth_items_set_int(items, "int", 45);
1200 // auth_items_set_flags(items, "int", 2);
1201 // auth_items_set_bool(items, "true", true);
1202 // auth_items_set_bool(items, "false", false);
1203 // auth_items_set(items, "com.apple.");
1204 // auth_show(items);
1205 // LOGD("Yeah it works: %s", auth_items_get_string(items, "test3"));
1206 // LOGD("Yeah it works: %i", auth_items_get_bool(items, "true"));
1207 // LOGD("Yeah it works: %i", auth_items_get_bool(items, "false"));
1208 // LOGD("Yeah it works: %i", auth_items_get_int(items, "int"));
1209 // (void)auth_items_get_bool(items, "test3");
1210 // AuthorizationItemSet * itemSet = auth_items_get_item_set(items);
1211 // for (uint32_t i = 0; i < itemSet->count; i++) {
1212 // LOGD("item: %s", itemSet->items[i].name);
1213 // }
1214 //
1215 // xpc_object_t xpcdata = SerializeItemSet(auth_items_get_item_set(items));
1216 // auth_items_t items2 = auth_items_create_with_xpc(xpcdata);
1217 // xpc_release(xpcdata);
1218 // auth_items_remove_with_flags(items2, 7);
1219 //// auth_items_set_string(items2, "test3", "testing 3 very good");
1220 // auth_items_copy_with_flags(items2, items, 7);
1221 // LOGD("Yeah it works: %s", auth_items_get_string(items2, "test3"));
1222 // auth_show(items2);
1223 // CFReleaseSafe(items2);
1224 //
1225 // CFReleaseSafe(items);
1226 }
1227