1 /* Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */
9 #include "authd_private.h"
10 #include "connection.h"
12 #include <Security/Authorization.h>
15 #include <xpc/private.h>
16 #include <dispatch/dispatch.h>
21 #include <malloc/malloc.h>
27 security_auth_peer_event_handler(xpc_connection_t connection
, xpc_object_t event
)
29 __block OSStatus status
= errAuthorizationDenied
;
31 connection_t conn
= (connection_t
)xpc_connection_get_context(connection
);
32 require_action(conn
!= NULL
, done
, os_log_error(AUTHD_LOG
, "xpc: process context not found"));
36 xpc_type_t type
= xpc_get_type(event
);
38 if (type
== XPC_TYPE_ERROR
) {
39 if (event
== XPC_ERROR_CONNECTION_INVALID
) {
40 // The client process on the other end of the connection has either
41 // crashed or canceled the connection. After receiving this error,
42 // the connection is in an invalid state, and you do not need to
43 // call xpc_connection_cancel(). Just tear down any associated state
45 os_log_debug(AUTHD_LOG
, "xpc: client disconnected PID %d", xpc_connection_get_pid(connection
));
46 connection_destroy_agents(conn
);
47 } else if (event
== XPC_ERROR_TERMINATION_IMMINENT
) {
48 // Handle per-connection termination cleanup.
49 os_log_debug(AUTHD_LOG
, "xpc: per-connection termination PID %d", xpc_connection_get_pid(connection
));
52 assert(type
== XPC_TYPE_DICTIONARY
);
54 xpc_object_t reply
= xpc_dictionary_create_reply(event
);
55 require(reply
!= NULL
, done
);
57 uint64_t auth_type
= xpc_dictionary_get_uint64(event
, AUTH_XPC_TYPE
);
58 os_log_debug(AUTHD_LOG
, "xpc: received message PID %d, type=%llu", connection_get_pid(conn
), auth_type
);
61 case AUTHORIZATION_CREATE
:
62 status
= authorization_create(conn
,event
,reply
);
64 case AUTHORIZATION_CREATE_WITH_AUDIT_TOKEN
:
65 status
= authorization_create_with_audit_token(conn
,event
,reply
);
67 case AUTHORIZATION_FREE
:
68 status
= authorization_free(conn
,event
,reply
);
70 case AUTHORIZATION_COPY_RIGHTS
:
71 status
= authorization_copy_rights(conn
,event
,reply
);
73 case AUTHORIZATION_COPY_INFO
:
74 status
= authorization_copy_info(conn
,event
,reply
);
76 case AUTHORIZATION_MAKE_EXTERNAL_FORM
:
77 status
= authorization_make_external_form(conn
,event
,reply
);
79 case AUTHORIZATION_CREATE_FROM_EXTERNAL_FORM
:
80 status
= authorization_create_from_external_form(conn
,event
,reply
);
82 case AUTHORIZATION_RIGHT_GET
:
83 status
= authorization_right_get(conn
,event
,reply
);
85 case AUTHORIZATION_RIGHT_SET
:
86 status
= authorization_right_set(conn
,event
,reply
);
88 case AUTHORIZATION_RIGHT_REMOVE
:
89 status
= authorization_right_remove(conn
,event
,reply
);
91 case SESSION_SET_USER_PREFERENCES
:
92 status
= session_set_user_preferences(conn
,event
,reply
);
94 case AUTHORIZATION_DISMISS
:
95 connection_destroy_agents(conn
);
96 status
= errAuthorizationSuccess
;
98 case AUTHORIZATION_ENABLE_SMARTCARD
:
99 status
= authorization_enable_smartcard(conn
,event
,reply
);
101 case AUTHORIZATION_SETUP
:
103 mach_port_t bootstrap
= xpc_dictionary_copy_mach_send(event
, AUTH_XPC_BOOTSTRAP
);
104 if (!process_set_bootstrap(connection_get_process(conn
), bootstrap
)) {
105 if (bootstrap
!= MACH_PORT_NULL
) {
106 mach_port_deallocate(mach_task_self(), bootstrap
);
110 status
= errAuthorizationSuccess
;
112 case AUTHORIZATION_PREAUTHORIZE_CREDENTIALS
:
113 status
= authorization_preauthorize_credentials(conn
,event
,reply
);
116 case AUTHORIZATION_DEV
:
124 xpc_dictionary_set_int64(reply
, AUTH_XPC_STATUS
, status
);
125 xpc_connection_send_message(connection
, reply
);
134 connection_finalizer(void * conn
)
136 os_log_debug(AUTHD_LOG
, "xpc: connection_finalizer for PID %d", connection_get_pid(conn
));
137 server_unregister_connection(conn
);
140 // malloc_printf("-=-=-=- connection_finalizer() -=-=-=-\n");
141 // malloc_zone_print(malloc_default_zone(), false);
146 security_auth_event_handler(xpc_connection_t xpc_conn
)
148 connection_t conn
= server_register_connection(xpc_conn
);
151 xpc_connection_set_context(xpc_conn
, conn
);
152 xpc_connection_set_finalizer_f(xpc_conn
, connection_finalizer
);
154 xpc_connection_set_event_handler(xpc_conn
, ^(xpc_object_t event
) {
155 xpc_retain(xpc_conn
);
157 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0), ^{
158 security_auth_peer_event_handler(xpc_conn
, event
);
160 xpc_release(xpc_conn
);
163 xpc_connection_resume(xpc_conn
);
166 os_log_error(AUTHD_LOG
, "xpc: failed to register connection (PID %d)", xpc_connection_get_pid(xpc_conn
));
167 xpc_connection_cancel(xpc_conn
);
171 static void sandbox(const char *tmpdir
)
174 const char *sandbox_params
[] = {"TMP_DIR", tmpdir
, NULL
};
177 rc
= sandbox_init_with_parameters(SECURITY_AUTH_NAME
, SANDBOX_NAMED
, sandbox_params
, &errorbuf
);
179 os_log_error(AUTHD_LOG
, "server: sandbox_init failed %{public}s (%i)", errorbuf
, rc
);
180 sandbox_free_error(errorbuf
);
187 int main(int argc AUTH_UNUSED
, const char *argv
[] AUTH_UNUSED
)
190 // malloc_printf("-=-=-=- main() -=-=-=-\n");
191 // malloc_zone_print(malloc_default_zone(), false);
194 os_log_debug(AUTHD_LOG
, "starting");
196 // <rdar://problem/20900280> authd needs to provide a writeable temp dir for SQLite
197 // <rdar://problem/21223798> Insecure temporary directory in authd (/tmp/authd)
198 char darwin_tmp
[PATH_MAX
];
199 size_t len
= confstr(_CS_DARWIN_USER_TEMP_DIR
, darwin_tmp
, sizeof(darwin_tmp
));
200 if (len
== 0 || len
>= PATH_MAX
) {
201 os_log_error(AUTHD_LOG
, "Invalid _CS_DARWIN_USER_TEMP_DIR");
202 return errAuthorizationInternal
;
205 char *real_tmp
= realpath(darwin_tmp
, NULL
);
206 if (real_tmp
== NULL
) {
207 os_log_error(AUTHD_LOG
, "realpath( %{public}s ) FAILED", darwin_tmp
);
208 return errAuthorizationInternal
;
211 setenv("SQLITE_TMPDIR", real_tmp
, 1);
215 if (server_init() != errAuthorizationSuccess
) {
216 os_log_error(AUTHD_LOG
, "auth: server_init() failed");
217 return errAuthorizationInternal
;
221 // malloc_printf("-=-=-=- server_init() -=-=-=-\n");
222 // malloc_zone_print(malloc_default_zone(), false);
225 xpc_main(security_auth_event_handler
);
227 // xpc_main() will never return, but if it did, here's what you'd call: