]> git.saurik.com Git - apple/security.git/blob - securityd/securityd_service/securityd_service/securityd_service_client.c
851586db8a6277ac35c6e0a7c4936e40995cd16f
[apple/security.git] / securityd / securityd_service / securityd_service / securityd_service_client.c
1 /* Copyright (c) 2013-2014 Apple Inc. All Rights Reserved. */
2
3 #include "securityd_service.h"
4 #include "securityd_service_client.h"
5 #include <xpc/xpc.h>
6 #include <dispatch/dispatch.h>
7 #include <syslog.h>
8 #include <AssertMacros.h>
9
10 static xpc_connection_t
11 _service_get_connection()
12 {
13 static dispatch_once_t onceToken;
14 static xpc_connection_t connection = NULL;
15
16 dispatch_once(&onceToken, ^{
17 connection = xpc_connection_create_mach_service(SECURITYD_SERVICE_NAME, NULL, XPC_CONNECTION_MACH_SERVICE_PRIVILEGED);
18 require(connection, done);
19
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");
24 }
25 // XPC_ERROR_CONNECTION_INTERRUPTED
26 // XPC_ERROR_TERMINATION_IMMINENT
27 } else {
28 char * desc = xpc_copy_description(event);
29 syslog(LOG_ERR, "securityd_service should never get messages on this connection: %s", desc);
30 free(desc);
31 }
32 });
33
34 xpc_connection_resume(connection);
35 done:
36 return;
37 });
38
39 return connection;
40 }
41
42 static int
43 _service_send_msg(service_context_t *context, xpc_object_t message, xpc_object_t * reply_out)
44 {
45 int rc = KB_GeneralError;
46 xpc_object_t reply = NULL;
47 xpc_connection_t conn = NULL;
48
49 require(message, done);
50 conn = _service_get_connection();
51 require(conn, done);
52
53 if (context) {
54 xpc_dictionary_set_data(message, SERVICE_XPC_CONTEXT, context, sizeof(service_context_t));
55 }
56 reply = xpc_connection_send_message_with_reply_sync(conn, message);
57 require(reply, done);
58 require(xpc_get_type(reply) != XPC_TYPE_ERROR, done);
59
60 rc = (int)xpc_dictionary_get_int64(reply, SERVICE_XPC_RC);
61
62 if (reply_out) {
63 *reply_out = reply;
64 reply = NULL;
65 }
66
67 done:
68 if (reply) xpc_release(reply);
69 return rc;
70 }
71
72 int
73 _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)
74 {
75 int rc = KB_GeneralError;
76 xpc_object_t message = NULL;
77
78 message = xpc_dictionary_create(NULL, NULL, 0);
79 require_quiet(message, done);
80
81 xpc_dictionary_set_uint64(message, SERVICE_XPC_REQUEST, request);
82 if (secret) {
83 xpc_dictionary_set_data(message, SERVICE_XPC_SECRET, secret, secret_len);
84 }
85
86 if (new_secret) {
87 xpc_dictionary_set_data(message, SERVICE_XPC_SECRET_NEW, new_secret, new_secret_len);
88 }
89
90 rc = _service_send_msg(context, message, NULL);
91
92 done:
93 if (message) xpc_release(message);
94 return rc;
95 }
96
97 int
98 service_client_kb_create(service_context_t *context, const void * secret, int secret_len)
99 {
100 return _service_client_send_secret(context, SERVICE_KB_CREATE, secret, secret_len, NULL, 0);
101 }
102
103 int
104 service_client_kb_load(service_context_t *context)
105 {
106 return _service_client_send_secret(context, SERVICE_KB_LOAD, NULL, 0, NULL, 0);
107 }
108
109 int
110 service_client_kb_unload(service_context_t *context)
111 {
112 return _service_client_send_secret(context, SERVICE_KB_UNLOAD, NULL, 0, NULL, 0);
113 }
114
115 int
116 service_client_kb_save(service_context_t *context)
117 {
118 return _service_client_send_secret(context, SERVICE_KB_SAVE, NULL, 0, NULL, 0);
119 }
120
121 int
122 service_client_kb_unlock(service_context_t *context, const void * secret, int secret_len)
123 {
124 return _service_client_send_secret(context, SERVICE_KB_UNLOCK, secret, secret_len, NULL, 0);
125 }
126
127 int
128 service_client_kb_lock(service_context_t *context)
129 {
130 return _service_client_send_secret(context, SERVICE_KB_LOCK, NULL, 0, NULL, 0);
131 }
132
133 int
134 service_client_kb_change_secret(service_context_t *context, const void * secret, int secret_len, const void * new_secret, int new_secret_len)
135 {
136 return _service_client_send_secret(context, SERVICE_KB_CHANGE_SECRET, secret, secret_len, new_secret, new_secret_len);
137 }
138
139 int
140 service_client_kb_reset(service_context_t *context, const void * secret, int secret_len)
141 {
142 return _service_client_send_secret(context, SERVICE_KB_RESET, secret, secret_len, NULL, 0);
143 }
144
145 int service_client_kb_is_locked(service_context_t *context, bool *locked, bool *no_pin)
146 {
147 int rc = KB_GeneralError;
148 xpc_object_t message = NULL;
149 xpc_object_t reply = NULL;
150
151 if (locked) *locked = false;
152 if (no_pin) *no_pin = false;
153
154 message = xpc_dictionary_create(NULL, NULL, 0);
155 require_quiet(message, done);
156
157 xpc_dictionary_set_uint64(message, SERVICE_XPC_REQUEST, SERVICE_KB_IS_LOCKED);
158
159 rc = _service_send_msg(context, message, &reply);
160
161 if (rc == KB_Success) {
162 if (locked) {
163 *locked = xpc_dictionary_get_bool(reply, SERVICE_XPC_LOCKED);
164 }
165 if (no_pin) {
166 *no_pin = xpc_dictionary_get_bool(reply, SERVICE_XPC_NO_PIN);
167 }
168 }
169
170 done:
171 if (message) xpc_release(message);
172 if (reply) xpc_release(reply);
173 return rc;
174 }
175
176 int
177 service_client_stash_set_key(service_context_t *context, const void * key, int key_len)
178 {
179 int rc = KB_GeneralError;
180 xpc_object_t message = NULL;
181
182 message = xpc_dictionary_create(NULL, NULL, 0);
183 require_quiet(message, done);
184
185 xpc_dictionary_set_uint64(message, SERVICE_XPC_REQUEST, SERVICE_STASH_SET_KEY);
186
187 if (key)
188 xpc_dictionary_set_data(message, SERVICE_XPC_KEY, key, key_len);
189
190 rc = _service_send_msg(context, message, NULL);
191
192 done:
193 if (message) xpc_release(message);
194 return rc;
195 }
196
197 int
198 service_client_stash_load_key(service_context_t *context, const void * key, int key_len)
199 {
200 int rc = KB_GeneralError;
201 xpc_object_t message = NULL;
202
203 message = xpc_dictionary_create(NULL, NULL, 0);
204 require_quiet(message, done);
205
206 xpc_dictionary_set_uint64(message, SERVICE_XPC_REQUEST, SERVICE_STASH_LOAD_KEY);
207
208 if (key)
209 xpc_dictionary_set_data(message, SERVICE_XPC_KEY, key, key_len);
210
211 rc = _service_send_msg(context, message, NULL);
212
213 done:
214 if (message) xpc_release(message);
215 return rc;
216 }
217
218 int
219 service_client_stash_get_key(service_context_t *context, void ** key, int * key_len)
220 {
221 int rc = KB_GeneralError;
222 xpc_object_t message = NULL;
223 xpc_object_t reply = NULL;
224
225 require(key, done);
226 require(key_len, done);
227
228 message = xpc_dictionary_create(NULL, NULL, 0);
229 require_quiet(message, done);
230
231 xpc_dictionary_set_uint64(message, SERVICE_XPC_REQUEST, SERVICE_STASH_GET_KEY);
232
233 rc = _service_send_msg(context, message, &reply);
234
235 if (rc == KB_Success) {
236 size_t data_len = 0;
237 const void * data = xpc_dictionary_get_data(reply, SERVICE_XPC_KEY, &data_len);
238 if (data) {
239 *key = calloc(1u, data_len);
240 memcpy(*key, data, data_len);
241 *key_len = (int)data_len;
242 }
243 }
244
245 done:
246 if (message) xpc_release(message);
247 if (reply) xpc_release(reply);
248 return rc;
249 }