]> git.saurik.com Git - apple/security.git/blob - OSX/authd/main.c
Security-59754.80.3.tar.gz
[apple/security.git] / OSX / authd / main.c
1 /* Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */
2
3 #include "debugging.h"
4 #include "server.h"
5 #include "process.h"
6 #include "session.h"
7 #include "authtoken.h"
8 #include "engine.h"
9 #include "authd_private.h"
10 #include "connection.h"
11
12 #include <Security/Authorization.h>
13
14 #include <xpc/xpc.h>
15 #include <xpc/private.h>
16 #include <dispatch/dispatch.h>
17 #include <security_utilities/simulatecrash_assert.h>
18 #include <sandbox.h>
19
20 #if DEBUG
21 #include <malloc/malloc.h>
22 #endif
23
24 AUTHD_DEFINE_LOG
25
26 static void
27 security_auth_peer_event_handler(xpc_connection_t connection, xpc_object_t event)
28 {
29 __block OSStatus status = errAuthorizationDenied;
30
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"));
33
34 CFRetainSafe(conn);
35
36 xpc_type_t type = xpc_get_type(event);
37
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
44 // here.
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));
50 }
51 } else {
52 assert(type == XPC_TYPE_DICTIONARY);
53
54 xpc_object_t reply = xpc_dictionary_create_reply(event);
55 require(reply != NULL, done);
56
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);
59
60 switch (auth_type) {
61 case AUTHORIZATION_CREATE:
62 status = authorization_create(conn,event,reply);
63 break;
64 case AUTHORIZATION_CREATE_WITH_AUDIT_TOKEN:
65 status = authorization_create_with_audit_token(conn,event,reply);
66 break;
67 case AUTHORIZATION_FREE:
68 status = authorization_free(conn,event,reply);
69 break;
70 case AUTHORIZATION_COPY_RIGHTS:
71 status = authorization_copy_rights(conn,event,reply);
72 break;
73 case AUTHORIZATION_COPY_INFO:
74 status = authorization_copy_info(conn,event,reply);
75 break;
76 case AUTHORIZATION_MAKE_EXTERNAL_FORM:
77 status = authorization_make_external_form(conn,event,reply);
78 break;
79 case AUTHORIZATION_CREATE_FROM_EXTERNAL_FORM:
80 status = authorization_create_from_external_form(conn,event,reply);
81 break;
82 case AUTHORIZATION_RIGHT_GET:
83 status = authorization_right_get(conn,event,reply);
84 break;
85 case AUTHORIZATION_RIGHT_SET:
86 status = authorization_right_set(conn,event,reply);
87 break;
88 case AUTHORIZATION_RIGHT_REMOVE:
89 status = authorization_right_remove(conn,event,reply);
90 break;
91 case SESSION_SET_USER_PREFERENCES:
92 status = session_set_user_preferences(conn,event,reply);
93 break;
94 case AUTHORIZATION_DISMISS:
95 connection_destroy_agents(conn);
96 status = errAuthorizationSuccess;
97 break;
98 case AUTHORIZATION_ENABLE_SMARTCARD:
99 status = authorization_enable_smartcard(conn,event,reply);
100 break;
101 case AUTHORIZATION_SETUP:
102 {
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);
107 }
108 }
109 }
110 status = errAuthorizationSuccess;
111 break;
112 case AUTHORIZATION_COPY_RIGHT_PROPERTIES:
113 status = authorization_copy_right_properties(conn,event,reply);
114 break;
115 case AUTHORIZATION_COPY_PRELOGIN_USERDB:
116 status = authorization_copy_prelogin_userdb(conn,event,reply);
117 break;
118 #if DEBUG
119 case AUTHORIZATION_DEV:
120 server_dev();
121 break;
122 #endif
123 default:
124 break;
125 }
126
127 xpc_dictionary_set_int64(reply, AUTH_XPC_STATUS, status);
128 xpc_connection_send_message(connection, reply);
129 xpc_release(reply);
130 }
131
132 done:
133 CFReleaseSafe(conn);
134 }
135
136 static void
137 connection_finalizer(void * conn)
138 {
139 os_log_debug(AUTHD_LOG, "xpc: connection_finalizer for PID %d", connection_get_pid(conn));
140 server_unregister_connection(conn);
141
142 //#if DEBUG
143 // malloc_printf("-=-=-=- connection_finalizer() -=-=-=-\n");
144 // malloc_zone_print(malloc_default_zone(), false);
145 //#endif
146 }
147
148 static void
149 security_auth_event_handler(xpc_connection_t xpc_conn)
150 {
151 connection_t conn = server_register_connection(xpc_conn);
152
153 if (conn) {
154 xpc_connection_set_context(xpc_conn, conn);
155 xpc_connection_set_finalizer_f(xpc_conn, connection_finalizer);
156
157 xpc_connection_set_event_handler(xpc_conn, ^(xpc_object_t event) {
158 xpc_retain(xpc_conn);
159 xpc_retain(event);
160 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
161 security_auth_peer_event_handler(xpc_conn, event);
162 xpc_release(event);
163 xpc_release(xpc_conn);
164 });
165 });
166 xpc_connection_resume(xpc_conn);
167
168 } else {
169 os_log_error(AUTHD_LOG, "xpc: failed to register connection (PID %d)", xpc_connection_get_pid(xpc_conn));
170 xpc_connection_cancel(xpc_conn);
171 }
172 }
173
174 static void sandbox(const char *tmpdir)
175 {
176 char *errorbuf;
177 const char *sandbox_params[] = {"TMP_DIR", tmpdir, NULL};
178 int32_t rc;
179
180 rc = sandbox_init_with_parameters(SECURITY_AUTH_NAME, SANDBOX_NAMED, sandbox_params, &errorbuf);
181 if (rc) {
182 os_log_error(AUTHD_LOG, "server: sandbox_init failed %{public}s (%i)", errorbuf, rc);
183 sandbox_free_error(errorbuf);
184 #ifndef DEBUG
185 abort();
186 #endif
187 }
188 }
189
190 int main(int argc AUTH_UNUSED, const char *argv[] AUTH_UNUSED)
191 {
192 //#if DEBUG
193 // malloc_printf("-=-=-=- main() -=-=-=-\n");
194 // malloc_zone_print(malloc_default_zone(), false);
195 //#endif
196
197 os_log_debug(AUTHD_LOG, "starting");
198
199 // <rdar://problem/20900280> authd needs to provide a writeable temp dir for SQLite
200 // <rdar://problem/21223798> Insecure temporary directory in authd (/tmp/authd)
201 char darwin_tmp[PATH_MAX];
202 size_t len = confstr(_CS_DARWIN_USER_TEMP_DIR, darwin_tmp, sizeof(darwin_tmp));
203 if (len == 0 || len >= PATH_MAX) {
204 os_log_error(AUTHD_LOG, "Invalid _CS_DARWIN_USER_TEMP_DIR");
205 return errAuthorizationInternal;
206 }
207
208 char *real_tmp = realpath(darwin_tmp, NULL);
209 if (real_tmp == NULL) {
210 os_log_error(AUTHD_LOG, "realpath( %{public}s ) FAILED", darwin_tmp);
211 return errAuthorizationInternal;
212 }
213
214 setenv("SQLITE_TMPDIR", real_tmp, 1);
215 sandbox(real_tmp);
216 free(real_tmp);
217
218 if (server_init() != errAuthorizationSuccess) {
219 os_log_error(AUTHD_LOG, "auth: server_init() failed");
220 return errAuthorizationInternal;
221 }
222
223 //#if DEBUG
224 // malloc_printf("-=-=-=- server_init() -=-=-=-\n");
225 // malloc_zone_print(malloc_default_zone(), false);
226 //#endif
227
228 xpc_main(security_auth_event_handler);
229
230 // xpc_main() will never return, but if it did, here's what you'd call:
231 //server_cleanup();
232
233 return 0;
234 }