1 /* Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. */
3 #include "securityd_service.h"
4 #include "securityd_service_client.h"
6 #include <dispatch/dispatch.h>
8 #include <AssertMacros.h>
10 static xpc_connection_t
11 _service_get_connection()
13 static dispatch_once_t onceToken
;
14 static xpc_connection_t connection
= NULL
;
16 dispatch_once(&onceToken
, ^{
17 connection
= xpc_connection_create_mach_service(SECURITYD_SERVICE_NAME
, NULL
, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED
);
18 require(connection
, done
);
20 xpc_connection_set_event_handler(connection
, ^(xpc_object_t event
) {
21 if (xpc_get_type(event
) == XPC_TYPE_ERROR
) {
22 if (event
== XPC_ERROR_CONNECTION_INVALID
) {
23 syslog(LOG_ERR
, "securityd_service not available");
25 // XPC_ERROR_CONNECTION_INTERRUPTED
26 // XPC_ERROR_TERMINATION_IMMINENT
28 char * desc
= xpc_copy_description(event
);
29 syslog(LOG_ERR
, "securityd_service should never get messages on this connection: %s", desc
);
34 xpc_connection_resume(connection
);
43 _service_send_msg(service_context_t
*context
, xpc_object_t message
, xpc_object_t
* reply_out
)
45 int rc
= KB_GeneralError
;
46 xpc_object_t reply
= NULL
;
47 xpc_connection_t conn
= NULL
;
49 require(message
, done
);
50 conn
= _service_get_connection();
54 xpc_dictionary_set_data(message
, SERVICE_XPC_CONTEXT
, context
, sizeof(service_context_t
));
56 reply
= xpc_connection_send_message_with_reply_sync(conn
, message
);
58 require(xpc_get_type(reply
) != XPC_TYPE_ERROR
, done
);
60 rc
= (int)xpc_dictionary_get_int64(reply
, SERVICE_XPC_RC
);
68 if (reply
) xpc_release(reply
);
73 _service_client_send_uid(service_context_t
*context
, uint64_t request
, uid_t uid
)
75 int rc
= KB_GeneralError
;
76 xpc_object_t message
= NULL
;
78 message
= xpc_dictionary_create(NULL
, NULL
, 0);
79 require_quiet(message
, done
);
81 xpc_dictionary_set_uint64(message
, SERVICE_XPC_REQUEST
, request
);
82 xpc_dictionary_set_uint64(message
, SERVICE_XPC_UID
, uid
);
84 rc
= _service_send_msg(context
, message
, NULL
);
87 if (message
) xpc_release(message
);
93 _service_client_send_secret(service_context_t
*context
, uint64_t request
, const void * secret
, int secret_len
, const void * new_secret
, int new_secret_len
)
95 int rc
= KB_GeneralError
;
96 xpc_object_t message
= NULL
;
98 message
= xpc_dictionary_create(NULL
, NULL
, 0);
99 require_quiet(message
, done
);
101 xpc_dictionary_set_uint64(message
, SERVICE_XPC_REQUEST
, request
);
103 xpc_dictionary_set_data(message
, SERVICE_XPC_SECRET
, secret
, secret_len
);
107 xpc_dictionary_set_data(message
, SERVICE_XPC_SECRET_NEW
, new_secret
, new_secret_len
);
110 rc
= _service_send_msg(context
, message
, NULL
);
113 if (message
) xpc_release(message
);
118 service_client_kb_create(service_context_t
*context
, const void * secret
, int secret_len
)
120 return _service_client_send_secret(context
, SERVICE_KB_CREATE
, secret
, secret_len
, NULL
, 0);
124 service_client_kb_load(service_context_t
*context
)
126 return _service_client_send_secret(context
, SERVICE_KB_LOAD
, NULL
, 0, NULL
, 0);
130 service_client_kb_load_uid(uid_t uid
)
132 return _service_client_send_uid(NULL
, SERVICE_KB_LOAD_UID
, uid
);
136 service_client_kb_unload(service_context_t
*context
)
138 return _service_client_send_secret(context
, SERVICE_KB_UNLOAD
, NULL
, 0, NULL
, 0);
142 service_client_kb_save(service_context_t
*context
)
144 return _service_client_send_secret(context
, SERVICE_KB_SAVE
, NULL
, 0, NULL
, 0);
148 service_client_kb_unlock(service_context_t
*context
, const void * secret
, int secret_len
)
150 return _service_client_send_secret(context
, SERVICE_KB_UNLOCK
, secret
, secret_len
, NULL
, 0);
154 service_client_kb_lock(service_context_t
*context
)
156 return _service_client_send_secret(context
, SERVICE_KB_LOCK
, NULL
, 0, NULL
, 0);
160 service_client_kb_change_secret(service_context_t
*context
, const void * secret
, int secret_len
, const void * new_secret
, int new_secret_len
)
162 return _service_client_send_secret(context
, SERVICE_KB_CHANGE_SECRET
, secret
, secret_len
, new_secret
, new_secret_len
);
166 service_client_kb_reset(service_context_t
*context
, const void * secret
, int secret_len
)
168 return _service_client_send_secret(context
, SERVICE_KB_RESET
, secret
, secret_len
, NULL
, 0);
171 int service_client_kb_is_locked(service_context_t
*context
, bool *locked
, bool *no_pin
)
173 int rc
= KB_GeneralError
;
174 xpc_object_t message
= NULL
;
175 xpc_object_t reply
= NULL
;
177 if (locked
) *locked
= false;
178 if (no_pin
) *no_pin
= false;
180 message
= xpc_dictionary_create(NULL
, NULL
, 0);
181 require_quiet(message
, done
);
183 xpc_dictionary_set_uint64(message
, SERVICE_XPC_REQUEST
, SERVICE_KB_IS_LOCKED
);
185 rc
= _service_send_msg(context
, message
, &reply
);
187 if (rc
== KB_Success
) {
189 *locked
= xpc_dictionary_get_bool(reply
, SERVICE_XPC_LOCKED
);
192 *no_pin
= xpc_dictionary_get_bool(reply
, SERVICE_XPC_NO_PIN
);
197 if (message
) xpc_release(message
);
198 if (reply
) xpc_release(reply
);
203 service_client_stash_set_key(service_context_t
*context
, const void * key
, int key_len
)
205 int rc
= KB_GeneralError
;
206 xpc_object_t message
= NULL
;
208 message
= xpc_dictionary_create(NULL
, NULL
, 0);
209 require_quiet(message
, done
);
211 xpc_dictionary_set_uint64(message
, SERVICE_XPC_REQUEST
, SERVICE_STASH_SET_KEY
);
214 xpc_dictionary_set_data(message
, SERVICE_XPC_KEY
, key
, key_len
);
216 rc
= _service_send_msg(context
, message
, NULL
);
219 if (message
) xpc_release(message
);
224 service_client_stash_load_key(service_context_t
*context
, const void * key
, int key_len
)
226 int rc
= KB_GeneralError
;
227 xpc_object_t message
= NULL
;
229 message
= xpc_dictionary_create(NULL
, NULL
, 0);
230 require_quiet(message
, done
);
232 xpc_dictionary_set_uint64(message
, SERVICE_XPC_REQUEST
, SERVICE_STASH_LOAD_KEY
);
235 xpc_dictionary_set_data(message
, SERVICE_XPC_KEY
, key
, key_len
);
237 rc
= _service_send_msg(context
, message
, NULL
);
240 if (message
) xpc_release(message
);
245 service_client_stash_get_key(service_context_t
*context
, void ** key
, int * key_len
)
247 int rc
= KB_GeneralError
;
248 xpc_object_t message
= NULL
;
249 xpc_object_t reply
= NULL
;
252 require(key_len
, done
);
254 message
= xpc_dictionary_create(NULL
, NULL
, 0);
255 require_quiet(message
, done
);
257 xpc_dictionary_set_uint64(message
, SERVICE_XPC_REQUEST
, SERVICE_STASH_GET_KEY
);
259 rc
= _service_send_msg(context
, message
, &reply
);
261 if (rc
== KB_Success
) {
263 const void * data
= xpc_dictionary_get_data(reply
, SERVICE_XPC_KEY
, &data_len
);
265 *key
= calloc(1u, data_len
);
266 memcpy(*key
, data
, data_len
);
267 *key_len
= (int)data_len
;
272 if (message
) xpc_release(message
);
273 if (reply
) xpc_release(reply
);