summaryrefslogtreecommitdiffstats
path: root/src/misagent.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/misagent.c')
-rw-r--r--src/misagent.c290
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 */
44static 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 */
69static 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
92misagent_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
108misagent_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
115misagent_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
130misagent_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
167misagent_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
207misagent_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
247misagent_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
284int misagent_get_status_code(misagent_client_t client)
285{
286 if (!client) {
287 return -1;
288 }
289 return client->last_error;
290}