diff options
Diffstat (limited to 'src/misagent.c')
-rw-r--r-- | src/misagent.c | 290 |
1 files changed, 290 insertions, 0 deletions
diff --git a/src/misagent.c b/src/misagent.c new file mode 100644 index 0000000..e3da997 --- /dev/null +++ b/src/misagent.c | |||
@@ -0,0 +1,290 @@ | |||
1 | /* | ||
2 | * misagent.c | ||
3 | * com.apple.misagent service implementation. | ||
4 | * | ||
5 | * Copyright (c) 2012 Nikias Bassen, All Rights Reserved. | ||
6 | * | ||
7 | * This library is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU Lesser General Public | ||
9 | * License as published by the Free Software Foundation; either | ||
10 | * version 2.1 of the License, or (at your option) any later version. | ||
11 | * | ||
12 | * This library is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * Lesser General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU Lesser General Public | ||
18 | * License along with this library; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
20 | */ | ||
21 | |||
22 | #ifdef HAVE_CONFIG_H | ||
23 | #include <config.h> | ||
24 | #endif | ||
25 | #include <string.h> | ||
26 | #include <stdlib.h> | ||
27 | #include <unistd.h> | ||
28 | #include <plist/plist.h> | ||
29 | #include <stdio.h> | ||
30 | |||
31 | #include "misagent.h" | ||
32 | #include "property_list_service.h" | ||
33 | #include "common/debug.h" | ||
34 | |||
35 | /** | ||
36 | * Convert a property_list_service_error_t value to a misagent_error_t | ||
37 | * value. Used internally to get correct error codes. | ||
38 | * | ||
39 | * @param err A property_list_service_error_t error code | ||
40 | * | ||
41 | * @return A matching misagent_error_t error code, | ||
42 | * MISAGENT_E_UNKNOWN_ERROR otherwise. | ||
43 | */ | ||
44 | static misagent_error_t misagent_error(property_list_service_error_t err) | ||
45 | { | ||
46 | switch (err) { | ||
47 | case PROPERTY_LIST_SERVICE_E_SUCCESS: | ||
48 | return MISAGENT_E_SUCCESS; | ||
49 | case PROPERTY_LIST_SERVICE_E_INVALID_ARG: | ||
50 | return MISAGENT_E_INVALID_ARG; | ||
51 | case PROPERTY_LIST_SERVICE_E_PLIST_ERROR: | ||
52 | return MISAGENT_E_PLIST_ERROR; | ||
53 | case PROPERTY_LIST_SERVICE_E_MUX_ERROR: | ||
54 | return MISAGENT_E_CONN_FAILED; | ||
55 | default: | ||
56 | break; | ||
57 | } | ||
58 | return MISAGENT_E_UNKNOWN_ERROR; | ||
59 | } | ||
60 | |||
61 | /** | ||
62 | * Checks the response from misagent to determine if the operation | ||
63 | * was successful or an error occurred. Internally used only. | ||
64 | * | ||
65 | * @param response a PLIST_DICT received from device's misagent | ||
66 | * @param status_code pointer to an int that will be set to the status code | ||
67 | * contained in the response | ||
68 | */ | ||
69 | static misagent_error_t misagent_check_result(plist_t response, int* status_code) | ||
70 | { | ||
71 | if (plist_get_node_type(response) != PLIST_DICT) { | ||
72 | return MISAGENT_E_PLIST_ERROR; | ||
73 | } | ||
74 | |||
75 | plist_t node = plist_dict_get_item(response, "Status"); | ||
76 | if (!node || (plist_get_node_type(node) != PLIST_UINT)) { | ||
77 | return MISAGENT_E_PLIST_ERROR; | ||
78 | } | ||
79 | |||
80 | uint64_t val = -1LL; | ||
81 | plist_get_uint_val(node, &val); | ||
82 | if ((int64_t)val == -1LL) { | ||
83 | return MISAGENT_E_PLIST_ERROR; | ||
84 | } | ||
85 | *status_code = (int)(val & 0xFFFFFFFF); | ||
86 | if (*status_code == 0) { | ||
87 | return MISAGENT_E_SUCCESS; | ||
88 | } | ||
89 | return MISAGENT_E_REQUEST_FAILED; | ||
90 | } | ||
91 | |||
92 | misagent_error_t misagent_client_new(idevice_t device, lockdownd_service_descriptor_t service, misagent_client_t *client) | ||
93 | { | ||
94 | property_list_service_client_t plistclient = NULL; | ||
95 | misagent_error_t err = misagent_error(property_list_service_client_new(device, service, &plistclient)); | ||
96 | if (err != MISAGENT_E_SUCCESS) { | ||
97 | return err; | ||
98 | } | ||
99 | |||
100 | misagent_client_t client_loc = (misagent_client_t) malloc(sizeof(struct misagent_client_private)); | ||
101 | client_loc->parent = plistclient; | ||
102 | client_loc->last_error = 0; | ||
103 | |||
104 | *client = client_loc; | ||
105 | return MISAGENT_E_SUCCESS; | ||
106 | } | ||
107 | |||
108 | misagent_error_t misagent_client_start_service(idevice_t device, misagent_client_t * client, const char* label) | ||
109 | { | ||
110 | misagent_error_t err = MISAGENT_E_UNKNOWN_ERROR; | ||
111 | service_client_factory_start_service(device, MISAGENT_SERVICE_NAME, (void**)client, label, SERVICE_CONSTRUCTOR(misagent_client_new), &err); | ||
112 | return err; | ||
113 | } | ||
114 | |||
115 | misagent_error_t misagent_client_free(misagent_client_t client) | ||
116 | { | ||
117 | if (!client) | ||
118 | return MISAGENT_E_INVALID_ARG; | ||
119 | |||
120 | misagent_error_t err = MISAGENT_E_SUCCESS; | ||
121 | if (client->parent && client->parent->parent) { | ||
122 | misagent_error(property_list_service_client_free(client->parent)); | ||
123 | } | ||
124 | client->parent = NULL; | ||
125 | free(client); | ||
126 | |||
127 | return err; | ||
128 | } | ||
129 | |||
130 | misagent_error_t misagent_install(misagent_client_t client, plist_t profile) | ||
131 | { | ||
132 | if (!client || !client->parent || !profile || (plist_get_node_type(profile) != PLIST_DATA)) | ||
133 | return MISAGENT_E_INVALID_ARG; | ||
134 | |||
135 | client->last_error = MISAGENT_E_UNKNOWN_ERROR; | ||
136 | |||
137 | plist_t dict = plist_new_dict(); | ||
138 | plist_dict_set_item(dict, "MessageType", plist_new_string("Install")); | ||
139 | plist_dict_set_item(dict, "Profile", plist_copy(profile)); | ||
140 | plist_dict_set_item(dict, "ProfileType", plist_new_string("Provisioning")); | ||
141 | |||
142 | misagent_error_t res = misagent_error(property_list_service_send_xml_plist(client->parent, dict)); | ||
143 | plist_free(dict); | ||
144 | dict = NULL; | ||
145 | |||
146 | if (res != MISAGENT_E_SUCCESS) { | ||
147 | debug_info("could not send plist, error %d", res); | ||
148 | return res; | ||
149 | } | ||
150 | |||
151 | res = misagent_error(property_list_service_receive_plist(client->parent, &dict)); | ||
152 | if (res != MISAGENT_E_SUCCESS) { | ||
153 | debug_info("could not receive response, error %d", res); | ||
154 | return res; | ||
155 | } | ||
156 | if (!dict) { | ||
157 | debug_info("could not get response plist"); | ||
158 | return MISAGENT_E_UNKNOWN_ERROR; | ||
159 | } | ||
160 | |||
161 | res = misagent_check_result(dict, &client->last_error); | ||
162 | plist_free(dict); | ||
163 | |||
164 | return res; | ||
165 | } | ||
166 | |||
167 | misagent_error_t misagent_copy(misagent_client_t client, plist_t* profiles) | ||
168 | { | ||
169 | if (!client || !client->parent || !profiles) | ||
170 | return MISAGENT_E_INVALID_ARG; | ||
171 | |||
172 | client->last_error = MISAGENT_E_UNKNOWN_ERROR; | ||
173 | |||
174 | plist_t dict = plist_new_dict(); | ||
175 | plist_dict_set_item(dict, "MessageType", plist_new_string("Copy")); | ||
176 | plist_dict_set_item(dict, "ProfileType", plist_new_string("Provisioning")); | ||
177 | |||
178 | misagent_error_t res = misagent_error(property_list_service_send_xml_plist(client->parent, dict)); | ||
179 | plist_free(dict); | ||
180 | dict = NULL; | ||
181 | |||
182 | if (res != MISAGENT_E_SUCCESS) { | ||
183 | debug_info("could not send plist, error %d", res); | ||
184 | return res; | ||
185 | } | ||
186 | |||
187 | res = misagent_error(property_list_service_receive_plist(client->parent, &dict)); | ||
188 | if (res != MISAGENT_E_SUCCESS) { | ||
189 | debug_info("could not receive response, error %d", res); | ||
190 | return res; | ||
191 | } | ||
192 | if (!dict) { | ||
193 | debug_info("could not get response plist"); | ||
194 | return MISAGENT_E_UNKNOWN_ERROR; | ||
195 | } | ||
196 | |||
197 | res = misagent_check_result(dict, &client->last_error); | ||
198 | if (res == MISAGENT_E_SUCCESS) { | ||
199 | *profiles = plist_copy(plist_dict_get_item(dict, "Payload")); | ||
200 | } | ||
201 | plist_free(dict); | ||
202 | |||
203 | return res; | ||
204 | |||
205 | } | ||
206 | |||
207 | misagent_error_t misagent_copy_all(misagent_client_t client, plist_t* profiles) | ||
208 | { | ||
209 | if (!client || !client->parent || !profiles) | ||
210 | return MISAGENT_E_INVALID_ARG; | ||
211 | |||
212 | client->last_error = MISAGENT_E_UNKNOWN_ERROR; | ||
213 | |||
214 | plist_t dict = plist_new_dict(); | ||
215 | plist_dict_set_item(dict, "MessageType", plist_new_string("CopyAll")); | ||
216 | plist_dict_set_item(dict, "ProfileType", plist_new_string("Provisioning")); | ||
217 | |||
218 | misagent_error_t res = misagent_error(property_list_service_send_xml_plist(client->parent, dict)); | ||
219 | plist_free(dict); | ||
220 | dict = NULL; | ||
221 | |||
222 | if (res != MISAGENT_E_SUCCESS) { | ||
223 | debug_info("could not send plist, error %d", res); | ||
224 | return res; | ||
225 | } | ||
226 | |||
227 | res = misagent_error(property_list_service_receive_plist(client->parent, &dict)); | ||
228 | if (res != MISAGENT_E_SUCCESS) { | ||
229 | debug_info("could not receive response, error %d", res); | ||
230 | return res; | ||
231 | } | ||
232 | if (!dict) { | ||
233 | debug_info("could not get response plist"); | ||
234 | return MISAGENT_E_UNKNOWN_ERROR; | ||
235 | } | ||
236 | |||
237 | res = misagent_check_result(dict, &client->last_error); | ||
238 | if (res == MISAGENT_E_SUCCESS) { | ||
239 | *profiles = plist_copy(plist_dict_get_item(dict, "Payload")); | ||
240 | } | ||
241 | plist_free(dict); | ||
242 | |||
243 | return res; | ||
244 | |||
245 | } | ||
246 | |||
247 | misagent_error_t misagent_remove(misagent_client_t client, const char* profileID) | ||
248 | { | ||
249 | if (!client || !client->parent || !profileID) | ||
250 | return MISAGENT_E_INVALID_ARG; | ||
251 | |||
252 | client->last_error = MISAGENT_E_UNKNOWN_ERROR; | ||
253 | |||
254 | plist_t dict = plist_new_dict(); | ||
255 | plist_dict_set_item(dict, "MessageType", plist_new_string("Remove")); | ||
256 | plist_dict_set_item(dict, "ProfileID", plist_new_string(profileID)); | ||
257 | plist_dict_set_item(dict, "ProfileType", plist_new_string("Provisioning")); | ||
258 | |||
259 | misagent_error_t res = misagent_error(property_list_service_send_xml_plist(client->parent, dict)); | ||
260 | plist_free(dict); | ||
261 | dict = NULL; | ||
262 | |||
263 | if (res != MISAGENT_E_SUCCESS) { | ||
264 | debug_info("could not send plist, error %d", res); | ||
265 | return res; | ||
266 | } | ||
267 | |||
268 | res = misagent_error(property_list_service_receive_plist(client->parent, &dict)); | ||
269 | if (res != MISAGENT_E_SUCCESS) { | ||
270 | debug_info("could not receive response, error %d", res); | ||
271 | return res; | ||
272 | } | ||
273 | if (!dict) { | ||
274 | debug_info("could not get response plist"); | ||
275 | return MISAGENT_E_UNKNOWN_ERROR; | ||
276 | } | ||
277 | |||
278 | res = misagent_check_result(dict, &client->last_error); | ||
279 | plist_free(dict); | ||
280 | |||
281 | return res; | ||
282 | } | ||
283 | |||
284 | int misagent_get_status_code(misagent_client_t client) | ||
285 | { | ||
286 | if (!client) { | ||
287 | return -1; | ||
288 | } | ||
289 | return client->last_error; | ||
290 | } | ||