summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2010-01-11 21:22:58 +0100
committerGravatar Martin Szulecki2010-01-12 00:40:39 +0100
commit80744ee649c777da364e963a2af6244206ba5dfc (patch)
tree446bcf9870805153377799296ff010912e22ffc6 /src
parent3151cbe9969e1fb3b6fe2413b355b7f81ea62d2c (diff)
downloadlibimobiledevice-80744ee649c777da364e963a2af6244206ba5dfc.tar.gz
libimobiledevice-80744ee649c777da364e963a2af6244206ba5dfc.tar.bz2
Move plist code into a new property_list_service
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am1
-rw-r--r--src/property_list_service.c402
-rw-r--r--src/property_list_service.h60
3 files changed, 463 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 9b42f1c..0352f64 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -5,6 +5,7 @@ AM_LDFLAGS = $(libglib2_LIBS) $(libgnutls_LIBS) $(libtasn1_LIBS) $(libgthread2_L
5 5
6lib_LTLIBRARIES = libiphone.la 6lib_LTLIBRARIES = libiphone.la
7libiphone_la_SOURCES = iphone.c iphone.h \ 7libiphone_la_SOURCES = iphone.c iphone.h \
8 property_list_service.c property_list_service.h\
8 lockdown.c lockdown.h\ 9 lockdown.c lockdown.h\
9 AFC.c AFC.h\ 10 AFC.c AFC.h\
10 NotificationProxy.c NotificationProxy.h\ 11 NotificationProxy.c NotificationProxy.h\
diff --git a/src/property_list_service.c b/src/property_list_service.c
new file mode 100644
index 0000000..9d16bbc
--- /dev/null
+++ b/src/property_list_service.c
@@ -0,0 +1,402 @@
1/*
2 * property_list_service.c
3 * PropertyList service implementation.
4 *
5 * Copyright (c) 2010 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#include <stdlib.h>
22#include <string.h>
23#include <errno.h>
24#include <arpa/inet.h>
25
26#include "property_list_service.h"
27#include "iphone.h"
28#include "utils.h"
29
30/**
31 * Convert an iphone_error_t value to an property_list_service_error_t value.
32 * Used internally to get correct error codes.
33 *
34 * @param err An iphone_error_t error code
35 *
36 * @return A matching property_list_service_error_t error code,
37 * PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR otherwise.
38 */
39static property_list_service_error_t iphone_to_property_list_service_error(iphone_error_t err)
40{
41 switch (err) {
42 case IPHONE_E_SUCCESS:
43 return PROPERTY_LIST_SERVICE_E_SUCCESS;
44 case IPHONE_E_INVALID_ARG:
45 return PROPERTY_LIST_SERVICE_E_INVALID_ARG;
46 default:
47 break;
48 }
49 return PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR;
50}
51
52/**
53 * Creates a new property list service for the specified port.
54 *
55 * @param device The device to connect to.
56 * @param port The port on the device to connect to, usually opened by a call to
57 * lockdownd_start_service.
58 * @param client Pointer that will be set to a newly allocated
59 * property_list_service_client_t upon successful return.
60 *
61 * @return PROPERTY_LIST_SERVICE_E_SUCCESS on success,
62 * PROPERTY_LIST_SERVICE_E_INVALID_ARG when one of the arguments is invalid,
63 * or PROPERTY_LIST_SERVICE_E_MUX_ERROR when connecting to the device failed.
64 */
65property_list_service_error_t property_list_service_client_new(iphone_device_t device, uint16_t port, property_list_service_client_t *client)
66{
67 if (!device || port == 0 || !client || *client)
68 return PROPERTY_LIST_SERVICE_E_INVALID_ARG;
69
70 /* Attempt connection */
71 iphone_connection_t connection = NULL;
72 if (iphone_device_connect(device, port, &connection) != IPHONE_E_SUCCESS) {
73 return PROPERTY_LIST_SERVICE_E_MUX_ERROR;
74 }
75
76 /* create client object */
77 property_list_service_client_t client_loc = (property_list_service_client_t)malloc(sizeof(struct property_list_service_client_int));
78 client_loc->connection = connection;
79
80 *client = client_loc;
81
82 return PROPERTY_LIST_SERVICE_E_SUCCESS;
83}
84
85/**
86 * Frees a PropertyList service.
87 *
88 * @param client The property list service to free.
89 *
90 * @return PROPERTY_LIST_SERVICE_E_SUCCESS on success,
91 * PROPERTY_LIST_SERVICE_E_INVALID_ARG when client is invalid, or a
92 * PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR when another error occured.
93 */
94property_list_service_error_t property_list_service_client_free(property_list_service_client_t client)
95{
96 if (!client)
97 return PROPERTY_LIST_SERVICE_E_INVALID_ARG;
98
99 property_list_service_error_t err = iphone_to_property_list_service_error(iphone_device_disconnect(client->connection));
100 free(client);
101 return err;
102}
103
104/**
105 * Sends a plist using the given property list service client.
106 * Internally used generic plist send function.
107 *
108 * @param client The property list service client to use for sending.
109 * Can be NULL if ssl_session is non-NULL.
110 * @param plist plist to send
111 * @param binary 1 = send binary plist, 0 = send xml plist
112 * @param ssl_session If set to NULL, the communication will be unencrypted.
113 * For encrypted communication, pass a valid and properly initialized
114 * gnutls_session_t. client is ignored when ssl_session is non-NULL.
115 *
116 * @return PROPERTY_LIST_SERVICE_E_SUCCESS on success,
117 * PROPERTY_LIST_SERVICE_E_INVALID_ARG when one or more parameters are
118 * invalid, PROPERTY_LIST_SERVICE_E_PLIST_ERROR when dict is not a valid
119 * plist, or PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR when an unspecified
120 * error occurs.
121 */
122static property_list_service_error_t internal_plist_send(property_list_service_client_t client, plist_t plist, int binary, gnutls_session_t ssl_session)
123{
124 property_list_service_error_t res = PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR;
125 char *content = NULL;
126 uint32_t length = 0;
127 uint32_t nlen = 0;
128 int bytes = 0;
129
130 if ((!client && !ssl_session) || (client && !client->connection) || !plist) {
131 return PROPERTY_LIST_SERVICE_E_INVALID_ARG;
132 }
133
134 if (binary) {
135 plist_to_bin(plist, &content, &length);
136 } else {
137 plist_to_xml(plist, &content, &length);
138 }
139
140 if (!content || length == 0) {
141 return PROPERTY_LIST_SERVICE_E_PLIST_ERROR;
142 }
143
144 nlen = htonl(length);
145 log_debug_msg("%s: sending %d bytes\n", __func__, length);
146 if (ssl_session) {
147 bytes = gnutls_record_send(ssl_session, (const char*)&nlen, sizeof(nlen));
148 } else {
149 iphone_device_send(client->connection, (const char*)&nlen, sizeof(nlen), (uint32_t*)&bytes);
150 }
151 if (bytes == sizeof(nlen)) {
152 if (ssl_session) {
153 bytes = gnutls_record_send(ssl_session, content, length);
154 } else {
155 iphone_device_send(client->connection, content, length, (uint32_t*)&bytes);
156 }
157 if (bytes > 0) {
158 log_debug_msg("%s: sent %d bytes\n", __func__, bytes);
159 log_debug_buffer(content, bytes);
160 if ((uint32_t)bytes == length) {
161 res = PROPERTY_LIST_SERVICE_E_SUCCESS;
162 } else {
163 log_debug_msg("%s: ERROR: Could not send all data (%d of %d)!\n", __func__, bytes, length);
164 }
165 }
166 }
167 if (bytes <= 0) {
168 log_debug_msg("%s: ERROR: sending to device failed.\n", __func__);
169 }
170
171 free(content);
172
173 return res;
174}
175
176/**
177 * Sends an XML plist.
178 *
179 * @param client The property list service client to use for sending.
180 * @param plist plist to send
181 *
182 * @return PROPERTY_LIST_SERVICE_E_SUCCESS on success,
183 * PROPERTY_LIST_SERVICE_E_INVALID_ARG when client or plist is NULL,
184 * PROPERTY_LIST_SERVICE_E_PLIST_ERROR when dict is not a valid plist,
185 * or PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR when an unspecified error occurs.
186 */
187property_list_service_error_t property_list_service_send_xml_plist(property_list_service_client_t client, plist_t plist)
188{
189 return internal_plist_send(client, plist, 0, NULL);
190}
191
192/**
193 * Sends a binary plist.
194 *
195 * @param client The property list service client to use for sending.
196 * @param plist plist to send
197 *
198 * @return PROPERTY_LIST_SERVICE_E_SUCCESS on success,
199 * PROPERTY_LIST_SERVICE_E_INVALID_ARG when client or plist is NULL,
200 * PROPERTY_LIST_SERVICE_E_PLIST_ERROR when dict is not a valid plist,
201 * or PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR when an unspecified error occurs.
202 */
203property_list_service_error_t property_list_service_send_binary_plist(property_list_service_client_t client, plist_t plist)
204{
205 return internal_plist_send(client, plist, 1, NULL);
206}
207
208/**
209 * Sends an encrypted XML plist.
210 *
211 * @param ssl_session Valid and properly initialized gnutls_session_t.
212 * @param plist plist to send
213 *
214 * @return PROPERTY_LIST_SERVICE_E_SUCCESS on success,
215 * PROPERTY_LIST_SERVICE_E_INVALID_ARG when ssl_session or plist is NULL
216 * PROPERTY_LIST_SERVICE_E_PLIST_ERROR when dict is not a valid plist,
217 * or PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR when an unspecified error occurs.
218 */
219property_list_service_error_t property_list_service_send_encrypted_xml_plist(gnutls_session_t ssl_session, plist_t plist)
220{
221 return internal_plist_send(NULL, plist, 0, ssl_session);
222}
223
224/**
225 * Sends an encrypted binary plist.
226 *
227 * @param ssl_session Valid and properly initialized gnutls_session_t.
228 * @param plist plist to send
229 *
230 * @return PROPERTY_LIST_SERVICE_E_SUCCESS on success,
231 * PROPERTY_LIST_SERVICE_E_INVALID_ARG when ssl_session or plist is NULL,
232 * PROPERTY_LIST_SERVICE_E_PLIST_ERROR when dict is not a valid plist,
233 * or PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR when an unspecified error occurs.
234 */
235property_list_service_error_t property_list_service_send_encrypted_binary_plist(gnutls_session_t ssl_session, plist_t plist)
236{
237 return internal_plist_send(NULL, plist, 1, ssl_session);
238}
239
240/**
241 * Receives a plist using the given property list service client.
242 * Internally used generic plist receive function.
243 *
244 * @param client The property list service client to use for receiving
245 * @param plist pointer to a plist_t that will point to the received plist
246 * upon successful return
247 * @param timeout Maximum time in milliseconds to wait for data. This parameter
248 * is ignored when ssl_session is not NULL (i.e. encrypted communication is
249 * used). A timeout has to be implemented inside the functions passed to
250 * gnutls_transport_set_push_function / gnutls_transport_set_pull_function.
251 * @param ssl_session If set to NULL, the communication will be unencrypted.
252 * For encrypted communication, pass a valid and properly initialized
253 * gnutls_session_t.
254 *
255 * @return PROPERTY_LIST_SERVICE_E_SUCCESS on success,
256 * PROPERTY_LIST_SERVICE_E_INVALID_ARG when client or *plist is NULL,
257 * PROPERTY_LIST_SERVICE_E_PLIST_ERROR when the received data cannot be
258 * converted to a plist, PROPERTY_LIST_SERVICE_E_MUX_ERROR when a
259 * communication error occurs, or PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR when
260 * an unspecified error occurs.
261 */
262static property_list_service_error_t internal_plist_recv_timeout(property_list_service_client_t client, plist_t *plist, unsigned int timeout, gnutls_session_t ssl_session)
263{
264 property_list_service_error_t res = PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR;
265 uint32_t pktlen = 0;
266 uint32_t bytes = 0;
267
268 if ((!client && !ssl_session) || (client && !client->connection) || !plist) {
269 return PROPERTY_LIST_SERVICE_E_INVALID_ARG;
270 }
271
272 if (ssl_session) {
273 bytes = gnutls_record_recv(ssl_session, (char*)&pktlen, sizeof(pktlen));
274 } else {
275 iphone_device_recv_timeout(client->connection, (char*)&pktlen, sizeof(pktlen), &bytes, timeout);
276 }
277 log_debug_msg("%s: initial read=%i\n", __func__, bytes);
278 if (bytes < 4) {
279 log_debug_msg("%s: initial read failed!\n", __func__);
280 return PROPERTY_LIST_SERVICE_E_MUX_ERROR;
281 } else {
282 if ((char)pktlen == 0) { /* prevent huge buffers */
283 uint32_t curlen = 0;
284 char *content = NULL;
285 pktlen = ntohl(pktlen);
286 log_debug_msg("%s: %d bytes following\n", __func__, pktlen);
287 content = (char*)malloc(pktlen);
288
289 while (curlen < pktlen) {
290 if (ssl_session) {
291 bytes = gnutls_record_recv(ssl_session, content+curlen, pktlen-curlen);
292 } else {
293 iphone_device_recv(client->connection, content+curlen, pktlen-curlen, &bytes);
294 }
295 if (bytes <= 0) {
296 res = PROPERTY_LIST_SERVICE_E_MUX_ERROR;
297 break;
298 }
299 log_debug_msg("%s: received %d bytes\n", __func__, bytes);
300 curlen += bytes;
301 }
302 log_debug_buffer(content, pktlen);
303 if (!memcmp(content, "bplist00", 8)) {
304 plist_from_bin(content, pktlen, plist);
305 } else {
306 plist_from_xml(content, pktlen, plist);
307 }
308 if (*plist) {
309 res = PROPERTY_LIST_SERVICE_E_SUCCESS;
310 } else {
311 res = PROPERTY_LIST_SERVICE_E_PLIST_ERROR;
312 }
313 free(content);
314 content = NULL;
315 } else {
316 res = PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR;
317 }
318 }
319 return res;
320}
321
322/**
323 * Receives a plist using the given property list service client with specified
324 * timeout.
325 * Binary or XML plists are automatically handled.
326 *
327 * @param client The property list service client to use for receiving
328 * @param plist pointer to a plist_t that will point to the received plist
329 * upon successful return
330 * @param timeout Maximum time in milliseconds to wait for data.
331 *
332 * @return PROPERTY_LIST_SERVICE_E_SUCCESS on success,
333 * PROPERTY_LIST_SERVICE_E_INVALID_ARG when connection or *plist is NULL,
334 * PROPERTY_LIST_SERVICE_E_PLIST_ERROR when the received data cannot be
335 * converted to a plist, PROPERTY_LIST_SERVICE_E_MUX_ERROR when a
336 * communication error occurs, or PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR when
337 * an unspecified error occurs.
338 */
339property_list_service_error_t property_list_service_receive_plist_with_timeout(property_list_service_client_t client, plist_t *plist, unsigned int timeout)
340{
341 return internal_plist_recv_timeout(client, plist, timeout, NULL);
342}
343
344/**
345 * Receives a plist using the given property list service client.
346 * Binary or XML plists are automatically handled.
347 *
348 * This function is like property_list_service_receive_plist_with_timeout
349 * using a timeout of 10 seconds.
350 * @see property_list_service_receive_plist_with_timeout
351 *
352 * @param client The property list service client to use for receiving
353 * @param plist pointer to a plist_t that will point to the received plist
354 * upon successful return
355 *
356 * @return PROPERTY_LIST_SERVICE_E_SUCCESS on success,
357 * PROPERTY_LIST_SERVICE_E_INVALID_ARG when client or *plist is NULL,
358 * PROPERTY_LIST_SERVICE_E_PLIST_ERROR when the received data cannot be
359 * converted to a plist, PROPERTY_LIST_SERVICE_E_MUX_ERROR when a
360 * communication error occurs, or PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR when
361 * an unspecified error occurs.
362 */
363property_list_service_error_t property_list_service_receive_plist(property_list_service_client_t client, plist_t *plist)
364{
365 return internal_plist_recv_timeout(client, plist, 10000, NULL);
366}
367
368/**
369 * Receives an encrypted plist.
370 * Binary or XML plists are automatically handled.
371 * This function is like property_list_service_receive_encrypted_plist_with_timeout
372 * with a timeout value of 10 seconds.
373 *
374 * @param ssl_session Valid and properly initialized gnutls_session_t.
375 * @param plist pointer to a plist_t that will point to the received plist
376 * upon successful return
377 *
378 * @return PROPERTY_LIST_SERVICE_E_SUCCESS on success,
379 * PROPERTY_LIST_SERVICE_E_INVALID_ARG when ssl_session or *plist is NULL,
380 * PROPERTY_LIST_SERVICE_E_PLIST_ERROR when the received data cannot be
381 * converted to a plist, PROPERTY_LIST_SERVICE_E_MUX_ERROR when a
382 * communication error occurs, or PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR when
383 * an unspecified error occurs.
384 */
385property_list_service_error_t property_list_service_receive_encrypted_plist(gnutls_session_t ssl_session, plist_t *plist)
386{
387 return internal_plist_recv_timeout(NULL, plist, 10000, ssl_session);
388}
389
390/**
391 * Getter for the iphone_connection_t used by this client.
392 *
393 * @param client The property list service client to get the connection for.
394 *
395 * @return The connection used by client.
396 */
397iphone_connection_t property_list_service_get_connection(property_list_service_client_t client)
398{
399 if (!client)
400 return NULL;
401 return client->connection;
402}
diff --git a/src/property_list_service.h b/src/property_list_service.h
new file mode 100644
index 0000000..39d4a0c
--- /dev/null
+++ b/src/property_list_service.h
@@ -0,0 +1,60 @@
1 /*
2 * property_list_service.h
3 * Definitions for the PropertyList service
4 *
5 * Copyright (c) 2010 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#ifndef PROPERTY_LIST_SERVICE_H
22#define PROPERTY_LIST_SERVICE_H
23
24#include "iphone.h"
25
26/* Error Codes */
27#define PROPERTY_LIST_SERVICE_E_SUCCESS 0
28#define PROPERTY_LIST_SERVICE_E_INVALID_ARG -1
29#define PROPERTY_LIST_SERVICE_E_PLIST_ERROR -2
30#define PROPERTY_LIST_SERVICE_E_MUX_ERROR -3
31
32#define PROPERTY_LIST_SERVICE_E_UNKNOWN_ERROR -256
33
34struct property_list_service_client_int {
35 iphone_connection_t connection;
36};
37
38typedef struct property_list_service_client_int *property_list_service_client_t;
39
40typedef int16_t property_list_service_error_t;
41
42/* creation and destruction */
43property_list_service_error_t property_list_service_client_new(iphone_device_t device, uint16_t port, property_list_service_client_t *client);
44property_list_service_error_t property_list_service_client_free(property_list_service_client_t client);
45
46/* sending */
47property_list_service_error_t property_list_service_send_xml_plist(property_list_service_client_t client, plist_t plist);
48property_list_service_error_t property_list_service_send_binary_plist(property_list_service_client_t client, plist_t plist);
49property_list_service_error_t property_list_service_send_encrypted_xml_plist(gnutls_session_t ssl_session, plist_t plist);
50property_list_service_error_t property_list_service_send_encrypted_binary_plist(gnutls_session_t ssl_session, plist_t plist);
51
52/* receiving */
53property_list_service_error_t property_list_service_receive_plist_with_timeout(property_list_service_client_t client, plist_t *plist, unsigned int timeout);
54property_list_service_error_t property_list_service_receive_plist(property_list_service_client_t client, plist_t *plist);
55property_list_service_error_t property_list_service_receive_encrypted_plist(gnutls_session_t ssl_session, plist_t *plist);
56
57/* misc */
58iphone_connection_t property_list_service_get_connection(property_list_service_client_t client);
59
60#endif