]> git.saurik.com Git - apple/security.git/blob - securityd/securityd_service/securityd_service/securityd_service_client.c
b5e83a856452c2431bf20972aee3b9342b87edaf
[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(context, done);
50 require(message, done);
51 conn = _service_get_connection();
52 require(conn, done);
53
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_save(service_context_t *context)
111 {
112 return _service_client_send_secret(context, SERVICE_KB_SAVE, NULL, 0, NULL, 0);
113 }
114
115 int
116 service_client_kb_unlock(service_context_t *context, const void * secret, int secret_len)
117 {
118 return _service_client_send_secret(context, SERVICE_KB_UNLOCK, secret, secret_len, NULL, 0);
119 }
120
121 int
122 service_client_kb_lock(service_context_t *context)
123 {
124 return _service_client_send_secret(context, SERVICE_KB_LOCK, NULL, 0, NULL, 0);
125 }
126
127 int
128 service_client_kb_change_secret(service_context_t *context, const void * secret, int secret_len, const void * new_secret, int new_secret_len)
129 {
130 return _service_client_send_secret(context, SERVICE_KB_CHANGE_SECRET, secret, secret_len, new_secret, new_secret_len);
131 }
132
133 int
134 service_client_kb_reset(service_context_t *context, const void * secret, int secret_len)
135 {
136 return _service_client_send_secret(context, SERVICE_KB_RESET, secret, secret_len, NULL, 0);
137 }
138
139 int service_client_kb_is_locked(service_context_t *context, bool *locked, bool *no_pin)
140 {
141 int rc = KB_GeneralError;
142 xpc_object_t message = NULL;
143 xpc_object_t reply = NULL;
144
145 if (locked) *locked = false;
146 if (no_pin) *no_pin = false;
147
148 message = xpc_dictionary_create(NULL, NULL, 0);
149 require_quiet(message, done);
150
151 xpc_dictionary_set_uint64(message, SERVICE_XPC_REQUEST, SERVICE_KB_IS_LOCKED);
152
153 rc = _service_send_msg(context, message, &reply);
154
155 if (rc == KB_Success) {
156 if (locked) {
157 *locked = xpc_dictionary_get_bool(reply, SERVICE_XPC_LOCKED);
158 }
159 if (no_pin) {
160 *no_pin = xpc_dictionary_get_bool(reply, SERVICE_XPC_NO_PIN);
161 }
162 }
163
164 done:
165 if (message) xpc_release(message);
166 if (reply) xpc_release(reply);
167 return rc;
168 }
169
170 int
171 service_client_stash_set_key(service_context_t *context, const void * key, int key_len)
172 {
173 int rc = KB_GeneralError;
174 xpc_object_t message = NULL;
175
176 message = xpc_dictionary_create(NULL, NULL, 0);
177 require_quiet(message, done);
178
179 xpc_dictionary_set_uint64(message, SERVICE_XPC_REQUEST, SERVICE_STASH_SET_KEY);
180
181 if (key)
182 xpc_dictionary_set_data(message, SERVICE_XPC_KEY, key, key_len);
183
184 rc = _service_send_msg(context, message, NULL);
185
186 done:
187 if (message) xpc_release(message);
188 return rc;
189 }
190
191 int
192 service_client_stash_load_key(service_context_t *context, const void * key, int key_len)
193 {
194 int rc = KB_GeneralError;
195 xpc_object_t message = NULL;
196
197 message = xpc_dictionary_create(NULL, NULL, 0);
198 require_quiet(message, done);
199
200 xpc_dictionary_set_uint64(message, SERVICE_XPC_REQUEST, SERVICE_STASH_LOAD_KEY);
201
202 if (key)
203 xpc_dictionary_set_data(message, SERVICE_XPC_KEY, key, key_len);
204
205 rc = _service_send_msg(context, message, NULL);
206
207 done:
208 if (message) xpc_release(message);
209 return rc;
210 }
211
212 int
213 service_client_stash_get_key(service_context_t *context, void ** key, int * key_len)
214 {
215 int rc = KB_GeneralError;
216 xpc_object_t message = NULL;
217 xpc_object_t reply = NULL;
218
219 require(key, done);
220 require(key_len, done);
221
222 message = xpc_dictionary_create(NULL, NULL, 0);
223 require_quiet(message, done);
224
225 xpc_dictionary_set_uint64(message, SERVICE_XPC_REQUEST, SERVICE_STASH_GET_KEY);
226
227 rc = _service_send_msg(context, message, &reply);
228
229 if (rc == KB_Success) {
230 size_t data_len = 0;
231 const void * data = xpc_dictionary_get_data(reply, SERVICE_XPC_KEY, &data_len);
232 if (data) {
233 *key = calloc(1u, data_len);
234 memcpy(*key, data, data_len);
235 *key_len = (int)data_len;
236 }
237 }
238
239 done:
240 if (message) xpc_release(message);
241 if (reply) xpc_release(reply);
242 return rc;
243 }