]> git.saurik.com Git - apple/security.git/blob - OSX/authd/main.c
Security-57740.1.18.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 <assert.h>
18 #include <sandbox.h>
19
20 #if DEBUG
21 #include <malloc/malloc.h>
22 #endif
23
24 static void
25 security_auth_peer_event_handler(xpc_connection_t connection, xpc_object_t event)
26 {
27 __block OSStatus status = errAuthorizationDenied;
28
29 connection_t conn = (connection_t)xpc_connection_get_context(connection);
30 require_action(conn != NULL, done, LOGE("xpc[%i]: process context not found", xpc_connection_get_pid(connection)));
31
32 CFRetainSafe(conn);
33
34 xpc_type_t type = xpc_get_type(event);
35
36 if (type == XPC_TYPE_ERROR) {
37 if (event == XPC_ERROR_CONNECTION_INVALID) {
38 // The client process on the other end of the connection has either
39 // crashed or cancelled the connection. After receiving this error,
40 // the connection is in an invalid state, and you do not need to
41 // call xpc_connection_cancel(). Just tear down any associated state
42 // here.
43 LOGV("xpc[%i]: client disconnected", xpc_connection_get_pid(connection));
44 connection_destroy_agents(conn);
45 } else if (event == XPC_ERROR_TERMINATION_IMMINENT) {
46 // Handle per-connection termination cleanup.
47 LOGD("xpc[%i]: per-connection termination", xpc_connection_get_pid(connection));
48 }
49 } else {
50 assert(type == XPC_TYPE_DICTIONARY);
51
52 xpc_object_t reply = xpc_dictionary_create_reply(event);
53 require(reply != NULL, done);
54
55 uint64_t auth_type = xpc_dictionary_get_uint64(event, AUTH_XPC_TYPE);
56 LOGV("xpc[%i]: received message type=%llu", connection_get_pid(conn), auth_type);
57
58 switch (auth_type) {
59 case AUTHORIZATION_CREATE:
60 status = authorization_create(conn,event,reply);
61 break;
62 case AUTHORIZATION_CREATE_WITH_AUDIT_TOKEN:
63 status = authorization_create_with_audit_token(conn,event,reply);
64 break;
65 case AUTHORIZATION_FREE:
66 status = authorization_free(conn,event,reply);
67 break;
68 case AUTHORIZATION_COPY_RIGHTS:
69 status = authorization_copy_rights(conn,event,reply);
70 break;
71 case AUTHORIZATION_COPY_INFO:
72 status = authorization_copy_info(conn,event,reply);
73 break;
74 case AUTHORIZATION_MAKE_EXTERNAL_FORM:
75 status = authorization_make_external_form(conn,event,reply);
76 break;
77 case AUTHORIZATION_CREATE_FROM_EXTERNAL_FORM:
78 status = authorization_create_from_external_form(conn,event,reply);
79 break;
80 case AUTHORIZATION_RIGHT_GET:
81 status = authorization_right_get(conn,event,reply);
82 break;
83 case AUTHORIZATION_RIGHT_SET:
84 status = authorization_right_set(conn,event,reply);
85 break;
86 case AUTHORIZATION_RIGHT_REMOVE:
87 status = authorization_right_remove(conn,event,reply);
88 break;
89 case SESSION_SET_USER_PREFERENCES:
90 status = session_set_user_preferences(conn,event,reply);
91 break;
92 case AUTHORIZATION_DISMISS:
93 connection_destroy_agents(conn);
94 status = errAuthorizationSuccess;
95 break;
96 case AUTHORIZATION_ENABLE_SMARTCARD:
97 status = authorization_enable_smartcard(conn,event,reply);
98 break;
99 case AUTHORIZATION_SETUP:
100 {
101 mach_port_t bootstrap = xpc_dictionary_copy_mach_send(event, AUTH_XPC_BOOTSTRAP);
102 if (!process_set_bootstrap(connection_get_process(conn), bootstrap)) {
103 if (bootstrap != MACH_PORT_NULL) {
104 mach_port_deallocate(mach_task_self(), bootstrap);
105 }
106 }
107 }
108 status = errAuthorizationSuccess;
109 break;
110 #if DEBUG
111 case AUTHORIZATION_DEV:
112 server_dev();
113 break;
114 #endif
115 default:
116 break;
117 }
118
119 xpc_dictionary_set_int64(reply, AUTH_XPC_STATUS, status);
120 xpc_connection_send_message(connection, reply);
121 xpc_release(reply);
122 }
123
124 done:
125 CFReleaseSafe(conn);
126 }
127
128 static void
129 connection_finalizer(void * conn)
130 {
131 LOGD("xpc[%i]: connection_finalizer", connection_get_pid(conn));
132 server_unregister_connection(conn);
133
134 //#if DEBUG
135 // malloc_printf("-=-=-=- connection_finalizer() -=-=-=-\n");
136 // malloc_zone_print(malloc_default_zone(), false);
137 //#endif
138 }
139
140 static void
141 security_auth_event_handler(xpc_connection_t xpc_conn)
142 {
143 connection_t conn = server_register_connection(xpc_conn);
144
145 if (conn) {
146 xpc_connection_set_context(xpc_conn, conn);
147 xpc_connection_set_finalizer_f(xpc_conn, connection_finalizer);
148
149 xpc_connection_set_event_handler(xpc_conn, ^(xpc_object_t event) {
150 xpc_retain(xpc_conn);
151 xpc_retain(event);
152 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
153 security_auth_peer_event_handler(xpc_conn, event);
154 xpc_release(event);
155 xpc_release(xpc_conn);
156 });
157 });
158 xpc_connection_resume(xpc_conn);
159
160 } else {
161 LOGE("xpc[%i]: failed to register connection", xpc_connection_get_pid(xpc_conn));
162 xpc_connection_cancel(xpc_conn);
163 }
164 }
165
166 static void sandbox(const char *tmpdir)
167 {
168 char *errorbuf;
169 const char *sandbox_params[] = {"TMP_DIR", tmpdir, NULL};
170 int32_t rc;
171
172 rc = sandbox_init_with_parameters(SECURITY_AUTH_NAME, SANDBOX_NAMED, sandbox_params, &errorbuf);
173 if (rc) {
174 LOGE("server: sandbox_init failed %s (%i)", errorbuf, rc);
175 sandbox_free_error(errorbuf);
176 #ifndef DEBUG
177 abort();
178 #endif
179 }
180 }
181
182 int main(int argc AUTH_UNUSED, const char *argv[] AUTH_UNUSED)
183 {
184 //#if DEBUG
185 // malloc_printf("-=-=-=- main() -=-=-=-\n");
186 // malloc_zone_print(malloc_default_zone(), false);
187 //#endif
188
189 LOGV("starting");
190
191 // <rdar://problem/20900280> authd needs to provide a writeable temp dir for SQLite
192 // <rdar://problem/21223798> Insecure temporary directory in authd (/tmp/authd)
193 char darwin_tmp[PATH_MAX];
194 size_t len = confstr(_CS_DARWIN_USER_TEMP_DIR, darwin_tmp, sizeof(darwin_tmp));
195 if (len == 0 || len >= PATH_MAX) {
196 LOGE("Invalid _CS_DARWIN_USER_TEMP_DIR");
197 return errAuthorizationInternal;
198 }
199
200 char *real_tmp = realpath(darwin_tmp, NULL);
201 if (real_tmp == NULL) {
202 LOGE("realpath( %s ) FAILED", darwin_tmp);
203 return errAuthorizationInternal;
204 }
205
206 setenv("SQLITE_TMPDIR", real_tmp, 1);
207 sandbox(real_tmp);
208 free(real_tmp);
209
210 if (server_init() != errAuthorizationSuccess) {
211 LOGE("auth: server_init() failed");
212 return errAuthorizationInternal;
213 }
214
215 //#if DEBUG
216 // malloc_printf("-=-=-=- server_init() -=-=-=-\n");
217 // malloc_zone_print(malloc_default_zone(), false);
218 //#endif
219
220 xpc_main(security_auth_event_handler);
221
222 server_cleanup();
223
224 return 0;
225 }