summaryrefslogtreecommitdiffstats
path: root/src/misagent.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/misagent.c')
-rw-r--r--src/misagent.c294
1 files changed, 294 insertions, 0 deletions
diff --git a/src/misagent.c b/src/misagent.c
new file mode 100644
index 0000000..3fdca4d
--- /dev/null
+++ b/src/misagent.c
@@ -0,0 +1,294 @@
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 <stdio.h>
28
29#ifndef _MSC_VER
30#include <unistd.h>
31#endif
32
33#include <plist/plist.h>
34
35#include "misagent.h"
36#include "property_list_service.h"
37#include "common/debug.h"
38
39/**
40 * Convert a property_list_service_error_t value to a misagent_error_t
41 * value. Used internally to get correct error codes.
42 *
43 * @param err A property_list_service_error_t error code
44 *
45 * @return A matching misagent_error_t error code,
46 * MISAGENT_E_UNKNOWN_ERROR otherwise.
47 */
48static misagent_error_t misagent_error(property_list_service_error_t err)
49{
50 switch (err) {
51 case PROPERTY_LIST_SERVICE_E_SUCCESS:
52 return MISAGENT_E_SUCCESS;
53 case PROPERTY_LIST_SERVICE_E_INVALID_ARG:
54 return MISAGENT_E_INVALID_ARG;
55 case PROPERTY_LIST_SERVICE_E_PLIST_ERROR:
56 return MISAGENT_E_PLIST_ERROR;
57 case PROPERTY_LIST_SERVICE_E_MUX_ERROR:
58 return MISAGENT_E_CONN_FAILED;
59 default:
60 break;
61 }
62 return MISAGENT_E_UNKNOWN_ERROR;
63}
64
65/**
66 * Checks the response from misagent to determine if the operation
67 * was successful or an error occurred. Internally used only.
68 *
69 * @param response a PLIST_DICT received from device's misagent
70 * @param status_code pointer to an int that will be set to the status code
71 * contained in the response
72 */
73static misagent_error_t misagent_check_result(plist_t response, int* status_code)
74{
75 if (plist_get_node_type(response) != PLIST_DICT) {
76 return MISAGENT_E_PLIST_ERROR;
77 }
78
79 plist_t node = plist_dict_get_item(response, "Status");
80 if (!node || (plist_get_node_type(node) != PLIST_UINT)) {
81 return MISAGENT_E_PLIST_ERROR;
82 }
83
84 uint64_t val = -1LL;
85 plist_get_uint_val(node, &val);
86 if ((int64_t)val == -1LL) {
87 return MISAGENT_E_PLIST_ERROR;
88 }
89 *status_code = (int)(val & 0xFFFFFFFF);
90 if (*status_code == 0) {
91 return MISAGENT_E_SUCCESS;
92 }
93 return MISAGENT_E_REQUEST_FAILED;
94}
95
96misagent_error_t misagent_client_new(idevice_t device, lockdownd_service_descriptor_t service, misagent_client_t *client)
97{
98 property_list_service_client_t plistclient = NULL;
99 misagent_error_t err = misagent_error(property_list_service_client_new(device, service, &plistclient));
100 if (err != MISAGENT_E_SUCCESS) {
101 return err;
102 }
103
104 misagent_client_t client_loc = (misagent_client_t) malloc(sizeof(struct misagent_client_private));
105 client_loc->parent = plistclient;
106 client_loc->last_error = 0;
107
108 *client = client_loc;
109 return MISAGENT_E_SUCCESS;
110}
111
112misagent_error_t misagent_client_start_service(idevice_t device, misagent_client_t * client, const char* label)
113{
114 misagent_error_t err = MISAGENT_E_UNKNOWN_ERROR;
115 service_client_factory_start_service(device, MISAGENT_SERVICE_NAME, (void**)client, label, SERVICE_CONSTRUCTOR(misagent_client_new), &err);
116 return err;
117}
118
119misagent_error_t misagent_client_free(misagent_client_t client)
120{
121 if (!client)
122 return MISAGENT_E_INVALID_ARG;
123
124 misagent_error_t err = MISAGENT_E_SUCCESS;
125 if (client->parent && client->parent->parent) {
126 misagent_error(property_list_service_client_free(client->parent));
127 }
128 client->parent = NULL;
129 free(client);
130
131 return err;
132}
133
134misagent_error_t misagent_install(misagent_client_t client, plist_t profile)
135{
136 if (!client || !client->parent || !profile || (plist_get_node_type(profile) != PLIST_DATA))
137 return MISAGENT_E_INVALID_ARG;
138
139 client->last_error = MISAGENT_E_UNKNOWN_ERROR;
140
141 plist_t dict = plist_new_dict();
142 plist_dict_set_item(dict, "MessageType", plist_new_string("Install"));
143 plist_dict_set_item(dict, "Profile", plist_copy(profile));
144 plist_dict_set_item(dict, "ProfileType", plist_new_string("Provisioning"));
145
146 misagent_error_t res = misagent_error(property_list_service_send_xml_plist(client->parent, dict));
147 plist_free(dict);
148 dict = NULL;
149
150 if (res != MISAGENT_E_SUCCESS) {
151 debug_info("could not send plist, error %d", res);
152 return res;
153 }
154
155 res = misagent_error(property_list_service_receive_plist(client->parent, &dict));
156 if (res != MISAGENT_E_SUCCESS) {
157 debug_info("could not receive response, error %d", res);
158 return res;
159 }
160 if (!dict) {
161 debug_info("could not get response plist");
162 return MISAGENT_E_UNKNOWN_ERROR;
163 }
164
165 res = misagent_check_result(dict, &client->last_error);
166 plist_free(dict);
167
168 return res;
169}
170
171misagent_error_t misagent_copy(misagent_client_t client, plist_t* profiles)
172{
173 if (!client || !client->parent || !profiles)
174 return MISAGENT_E_INVALID_ARG;
175
176 client->last_error = MISAGENT_E_UNKNOWN_ERROR;
177
178 plist_t dict = plist_new_dict();
179 plist_dict_set_item(dict, "MessageType", plist_new_string("Copy"));
180 plist_dict_set_item(dict, "ProfileType", plist_new_string("Provisioning"));
181
182 misagent_error_t res = misagent_error(property_list_service_send_xml_plist(client->parent, dict));
183 plist_free(dict);
184 dict = NULL;
185
186 if (res != MISAGENT_E_SUCCESS) {
187 debug_info("could not send plist, error %d", res);
188 return res;
189 }
190
191 res = misagent_error(property_list_service_receive_plist(client->parent, &dict));
192 if (res != MISAGENT_E_SUCCESS) {
193 debug_info("could not receive response, error %d", res);
194 return res;
195 }
196 if (!dict) {
197 debug_info("could not get response plist");
198 return MISAGENT_E_UNKNOWN_ERROR;
199 }
200
201 res = misagent_check_result(dict, &client->last_error);
202 if (res == MISAGENT_E_SUCCESS) {
203 *profiles = plist_copy(plist_dict_get_item(dict, "Payload"));
204 }
205 plist_free(dict);
206
207 return res;
208
209}
210
211misagent_error_t misagent_copy_all(misagent_client_t client, plist_t* profiles)
212{
213 if (!client || !client->parent || !profiles)
214 return MISAGENT_E_INVALID_ARG;
215
216 client->last_error = MISAGENT_E_UNKNOWN_ERROR;
217
218 plist_t dict = plist_new_dict();
219 plist_dict_set_item(dict, "MessageType", plist_new_string("CopyAll"));
220 plist_dict_set_item(dict, "ProfileType", plist_new_string("Provisioning"));
221
222 misagent_error_t res = misagent_error(property_list_service_send_xml_plist(client->parent, dict));
223 plist_free(dict);
224 dict = NULL;
225
226 if (res != MISAGENT_E_SUCCESS) {
227 debug_info("could not send plist, error %d", res);
228 return res;
229 }
230
231 res = misagent_error(property_list_service_receive_plist(client->parent, &dict));
232 if (res != MISAGENT_E_SUCCESS) {
233 debug_info("could not receive response, error %d", res);
234 return res;
235 }
236 if (!dict) {
237 debug_info("could not get response plist");
238 return MISAGENT_E_UNKNOWN_ERROR;
239 }
240
241 res = misagent_check_result(dict, &client->last_error);
242 if (res == MISAGENT_E_SUCCESS) {
243 *profiles = plist_copy(plist_dict_get_item(dict, "Payload"));
244 }
245 plist_free(dict);
246
247 return res;
248
249}
250
251misagent_error_t misagent_remove(misagent_client_t client, const char* profileID)
252{
253 if (!client || !client->parent || !profileID)
254 return MISAGENT_E_INVALID_ARG;
255
256 client->last_error = MISAGENT_E_UNKNOWN_ERROR;
257
258 plist_t dict = plist_new_dict();
259 plist_dict_set_item(dict, "MessageType", plist_new_string("Remove"));
260 plist_dict_set_item(dict, "ProfileID", plist_new_string(profileID));
261 plist_dict_set_item(dict, "ProfileType", plist_new_string("Provisioning"));
262
263 misagent_error_t res = misagent_error(property_list_service_send_xml_plist(client->parent, dict));
264 plist_free(dict);
265 dict = NULL;
266
267 if (res != MISAGENT_E_SUCCESS) {
268 debug_info("could not send plist, error %d", res);
269 return res;
270 }
271
272 res = misagent_error(property_list_service_receive_plist(client->parent, &dict));
273 if (res != MISAGENT_E_SUCCESS) {
274 debug_info("could not receive response, error %d", res);
275 return res;
276 }
277 if (!dict) {
278 debug_info("could not get response plist");
279 return MISAGENT_E_UNKNOWN_ERROR;
280 }
281
282 res = misagent_check_result(dict, &client->last_error);
283 plist_free(dict);
284
285 return res;
286}
287
288int misagent_get_status_code(misagent_client_t client)
289{
290 if (!client) {
291 return -1;
292 }
293 return client->last_error;
294}