1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
|
cdef extern from "libimobiledevice/lockdown.h":
ctypedef enum lockdownd_error_t:
LOCKDOWN_E_SUCCESS
LOCKDOWN_E_INVALID_ARG
LOCKDOWN_E_INVALID_CONF
LOCKDOWN_E_PLIST_ERROR
LOCKDOWN_E_PAIRING_FAILED
LOCKDOWN_E_SSL_ERROR
LOCKDOWN_E_DICT_ERROR
LOCKDOWN_E_RECEIVE_TIMEOUT
LOCKDOWN_E_SET_VALUE_PROHIBITED
LOCKDOWN_E_GET_VALUE_PROHIBITED
LOCKDOWN_E_MUX_ERROR
LOCKDOWN_E_NO_RUNNING_SESSION
LOCKDOWN_E_INVALID_RESPONSE
LOCKDOWN_E_MISSING_KEY
LOCKDOWN_E_MISSING_VALUE
LOCKDOWN_E_GET_PROHIBITED
LOCKDOWN_E_SET_PROHIBITED
LOCKDOWN_E_REMOVE_PROHIBITED
LOCKDOWN_E_IMMUTABLE_VALUE
LOCKDOWN_E_PASSWORD_PROTECTED
LOCKDOWN_E_USER_DENIED_PAIRING
LOCKDOWN_E_PAIRING_DIALOG_RESPONSE_PENDING
LOCKDOWN_E_MISSING_HOST_ID
LOCKDOWN_E_INVALID_HOST_ID
LOCKDOWN_E_SESSION_ACTIVE
LOCKDOWN_E_SESSION_INACTIVE
LOCKDOWN_E_MISSING_SESSION_ID
LOCKDOWN_E_INVALID_SESSION_ID
LOCKDOWN_E_MISSING_SERVICE
LOCKDOWN_E_INVALID_SERVICE
LOCKDOWN_E_SERVICE_LIMIT
LOCKDOWN_E_MISSING_PAIR_RECORD
LOCKDOWN_E_SAVE_PAIR_RECORD_FAILED
LOCKDOWN_E_INVALID_PAIR_RECORD
LOCKDOWN_E_INVALID_ACTIVATION_RECORD
LOCKDOWN_E_MISSING_ACTIVATION_RECORD
LOCKDOWN_E_SERVICE_PROHIBITED
LOCKDOWN_E_ESCROW_LOCKED
LOCKDOWN_E_PAIRING_PROHIBITED_OVER_THIS_CONNECTION
LOCKDOWN_E_FMIP_PROTECTED
LOCKDOWN_E_MC_PROTECTED
LOCKDOWN_E_MC_CHALLENGE_REQUIRED
LOCKDOWN_E_UNKNOWN_ERROR
lockdownd_error_t lockdownd_client_new(idevice_t device, lockdownd_client_t *client, char *label)
lockdownd_error_t lockdownd_client_new_with_handshake(idevice_t device, lockdownd_client_t *client, char *label)
lockdownd_error_t lockdownd_client_free(lockdownd_client_t client)
lockdownd_error_t lockdownd_query_type(lockdownd_client_t client, char **tp)
lockdownd_error_t lockdownd_get_value(lockdownd_client_t client, char *domain, char *key, plist.plist_t *value)
lockdownd_error_t lockdownd_set_value(lockdownd_client_t client, char *domain, char *key, plist.plist_t value)
lockdownd_error_t lockdownd_remove_value(lockdownd_client_t client, char *domain, char *key)
lockdownd_error_t lockdownd_start_service(lockdownd_client_t client, char *identifier, lockdownd_service_descriptor_t *service)
lockdownd_error_t lockdownd_start_session(lockdownd_client_t client, char *host_id, char **session_id, int *ssl_enabled)
lockdownd_error_t lockdownd_stop_session(lockdownd_client_t client, char *session_id)
lockdownd_error_t lockdownd_send(lockdownd_client_t client, plist.plist_t plist)
lockdownd_error_t lockdownd_receive(lockdownd_client_t client, plist.plist_t *plist)
lockdownd_error_t lockdownd_pair(lockdownd_client_t client, lockdownd_pair_record_t pair_record)
lockdownd_error_t lockdownd_validate_pair(lockdownd_client_t client, lockdownd_pair_record_t pair_record)
lockdownd_error_t lockdownd_unpair(lockdownd_client_t client, lockdownd_pair_record_t pair_record)
lockdownd_error_t lockdownd_activate(lockdownd_client_t client, plist.plist_t activation_record)
lockdownd_error_t lockdownd_deactivate(lockdownd_client_t client)
lockdownd_error_t lockdownd_enter_recovery(lockdownd_client_t client)
lockdownd_error_t lockdownd_goodbye(lockdownd_client_t client)
lockdownd_error_t lockdownd_get_sync_data_classes(lockdownd_client_t client, char ***classes, int *count)
lockdownd_error_t lockdownd_data_classes_free(char **classes)
lockdownd_error_t lockdownd_service_descriptor_free(lockdownd_service_descriptor_t service)
cdef class LockdownError(BaseError):
def __init__(self, *args, **kwargs):
self._lookup_table = {
LOCKDOWN_E_SUCCESS: "Success",
LOCKDOWN_E_INVALID_ARG: "Invalid argument",
LOCKDOWN_E_INVALID_CONF: "Invalid configuration",
LOCKDOWN_E_PLIST_ERROR: "Property list error",
LOCKDOWN_E_PAIRING_FAILED: "Pairing failed",
LOCKDOWN_E_SSL_ERROR: "SSL error",
LOCKDOWN_E_DICT_ERROR: "Dictionary error",
LOCKDOWN_E_RECEIVE_TIMEOUT: "Receive timeout",
LOCKDOWN_E_MUX_ERROR: "Mux Protocol Error",
LOCKDOWN_E_NO_RUNNING_SESSION: "No running session",
LOCKDOWN_E_INVALID_RESPONSE: "Invalid response",
LOCKDOWN_E_MISSING_KEY: "Missing key",
LOCKDOWN_E_MISSING_VALUE: "Missing value",
LOCKDOWN_E_GET_PROHIBITED: "Get value prohibited",
LOCKDOWN_E_SET_PROHIBITED: "Set value prohibited",
LOCKDOWN_E_REMOVE_PROHIBITED: "Remove value prohibited",
LOCKDOWN_E_IMMUTABLE_VALUE: "Immutable value",
LOCKDOWN_E_PASSWORD_PROTECTED: "Password protected",
LOCKDOWN_E_USER_DENIED_PAIRING: "User denied pairing",
LOCKDOWN_E_PAIRING_DIALOG_RESPONSE_PENDING: "Pairing dialog response pending",
LOCKDOWN_E_MISSING_HOST_ID: "Missing host ID",
LOCKDOWN_E_INVALID_HOST_ID: "Invalid host ID",
LOCKDOWN_E_SESSION_ACTIVE: "Session active",
LOCKDOWN_E_SESSION_INACTIVE: "Session inactive",
LOCKDOWN_E_MISSING_SESSION_ID: "Missing session ID",
LOCKDOWN_E_INVALID_SESSION_ID: "Invalid session ID",
LOCKDOWN_E_MISSING_SERVICE: "Missing service",
LOCKDOWN_E_INVALID_SERVICE: "Invalid service",
LOCKDOWN_E_SERVICE_LIMIT: "Service limit reached",
LOCKDOWN_E_MISSING_PAIR_RECORD: "Missing pair record",
LOCKDOWN_E_SAVE_PAIR_RECORD_FAILED: "Saving pair record failed",
LOCKDOWN_E_INVALID_PAIR_RECORD: "Invalid pair record",
LOCKDOWN_E_INVALID_ACTIVATION_RECORD: "Invalid activation record",
LOCKDOWN_E_MISSING_ACTIVATION_RECORD: "Missing activation record",
LOCKDOWN_E_SERVICE_PROHIBITED: "Service prohibited",
LOCKDOWN_E_ESCROW_LOCKED: "Escrow locked",
LOCKDOWN_E_PAIRING_PROHIBITED_OVER_THIS_CONNECTION: "Pairing prohibited over this connection",
LOCKDOWN_E_FMIP_PROTECTED: "Find My iPhone/iPod/iPad protected",
LOCKDOWN_E_MC_PROTECTED: "MC protected",
LOCKDOWN_E_MC_CHALLENGE_REQUIRED: "MC challenge required",
LOCKDOWN_E_UNKNOWN_ERROR: "Unknown error"
}
BaseError.__init__(self, *args, **kwargs)
cdef class LockdownPairRecord:
#def __cinit__(self, bytes device_certificate, bytes host_certificate, bytes host_id, bytes root_certificate, *args, **kwargs):
property device_certificate:
def __get__(self):
cdef bytes result = self._c_record.device_certificate
return result
property host_certificate:
def __get__(self):
cdef bytes result = self._c_record.host_certificate
return result
property host_id:
def __get__(self):
cdef bytes result = self._c_record.host_id
return result
property root_certificate:
def __get__(self):
cdef bytes result = self._c_record.root_certificate
return result
cdef class LockdownServiceDescriptor(Base):
#def __cinit__(self, uint16_t port, uint8_t ssl_enabled, *args, **kwargs):
def __dealloc__(self):
cdef lockdownd_error_t err
if self._c_service_descriptor is not NULL:
err = lockdownd_service_descriptor_free(self._c_service_descriptor)
self._c_service_descriptor = NULL
self.handle_error(err)
property port:
def __get__(self):
return self._c_service_descriptor.port
property ssl_enabled:
def __get__(self):
return self._c_service_descriptor.ssl_enabled
cdef class LockdownClient(PropertyListService):
def __cinit__(self, iDevice device not None, bytes label=b'', bint handshake=True, *args, **kwargs):
cdef:
lockdownd_error_t err
char* c_label = NULL
if label:
c_label = label
if handshake:
err = lockdownd_client_new_with_handshake(device._c_dev, &self._c_client, c_label)
else:
err = lockdownd_client_new(device._c_dev, &self._c_client, c_label)
self.handle_error(err)
self.device = device
def __dealloc__(self):
cdef lockdownd_error_t err
if self._c_client is not NULL:
err = lockdownd_client_free(self._c_client)
self.handle_error(err)
cpdef bytes query_type(self):
cdef:
lockdownd_error_t err
char* c_type = NULL
bytes result
err = lockdownd_query_type(self._c_client, &c_type)
try:
self.handle_error(err)
result = c_type
return result
except BaseError, e:
raise
finally:
if c_type != NULL:
free(c_type)
cpdef plist.Node get_value(self, bytes domain=None, bytes key=None):
cdef:
lockdownd_error_t err
plist.plist_t c_node = NULL
char* c_domain = NULL
char* c_key = NULL
if domain is not None:
c_domain = domain
if key is not None:
c_key = key
err = lockdownd_get_value(self._c_client, c_domain, c_key, &c_node)
try:
self.handle_error(err)
return plist.plist_t_to_node(c_node)
except BaseError, e:
if c_node != NULL:
plist.plist_free(c_node)
raise
cpdef set_value(self, bytes domain, bytes key, object value):
cdef plist.plist_t c_node = plist.native_to_plist_t(value)
try:
self.handle_error(lockdownd_set_value(self._c_client, domain, key, c_node))
except BaseError, e:
raise
finally:
if c_node != NULL:
plist.plist_free(c_node)
cpdef remove_value(self, bytes domain, bytes key):
self.handle_error(lockdownd_remove_value(self._c_client, domain, key))
cpdef object start_service(self, object service):
cdef:
char* c_service_name = NULL
lockdownd_service_descriptor_t c_descriptor = NULL
LockdownServiceDescriptor result
if issubclass(service, BaseService) and \
service.__service_name__ is not None \
and isinstance(service.__service_name__, (str, bytes)):
c_service_name = <bytes>service.__service_name__
elif isinstance(service, (str, bytes)):
c_service_name = <bytes>service
else:
raise TypeError("LockdownClient.start_service() takes a BaseService or string as its first argument")
try:
self.handle_error(lockdownd_start_service(self._c_client, c_service_name, &c_descriptor))
result = LockdownServiceDescriptor.__new__(LockdownServiceDescriptor)
result._c_service_descriptor = c_descriptor
return result
except BaseError, e:
raise
cpdef object get_service_client(self, object service_class):
cdef:
LockdownServiceDescriptor descriptor
if not hasattr(service_class, '__service_name__') and \
not service_class.__service_name__ is not None \
and not isinstance(service_class.__service_name__, (str, bytes)):
raise TypeError("LockdownClient.get_service_client() takes a BaseService as its first argument")
descriptor = self.start_service(service_class)
return service_class(self.device, descriptor)
cpdef tuple start_session(self, bytes host_id):
cdef:
lockdownd_error_t err
char* c_session_id = NULL
bint ssl_enabled
bytes session_id
err = lockdownd_start_session(self._c_client, host_id, &c_session_id, <int *>&ssl_enabled)
try:
self.handle_error(err)
session_id = c_session_id
return (session_id, ssl_enabled)
except BaseError, e:
raise
finally:
if c_session_id != NULL:
free(c_session_id)
cpdef stop_session(self, bytes session_id):
self.handle_error(lockdownd_stop_session(self._c_client, session_id))
cpdef pair(self, object pair_record=None):
cdef lockdownd_pair_record_t c_pair_record = NULL
if pair_record is not None:
c_pair_record = (<LockdownPairRecord>pair_record)._c_record
self.handle_error(lockdownd_pair(self._c_client, c_pair_record))
cpdef validate_pair(self, object pair_record=None):
cdef lockdownd_pair_record_t c_pair_record = NULL
if pair_record is not None:
c_pair_record = (<LockdownPairRecord>pair_record)._c_record
self.handle_error(lockdownd_validate_pair(self._c_client, c_pair_record))
cpdef unpair(self, object pair_record=None):
cdef lockdownd_pair_record_t c_pair_record = NULL
if pair_record is not None:
c_pair_record = (<LockdownPairRecord>pair_record)._c_record
self.handle_error(lockdownd_unpair(self._c_client, c_pair_record))
cpdef activate(self, plist.Node activation_record):
self.handle_error(lockdownd_activate(self._c_client, activation_record._c_node))
cpdef deactivate(self):
self.handle_error(lockdownd_deactivate(self._c_client))
cpdef enter_recovery(self):
self.handle_error(lockdownd_enter_recovery(self._c_client))
cpdef goodbye(self):
self.handle_error(lockdownd_goodbye(self._c_client))
cpdef list get_sync_data_classes(self):
cdef:
char **classes = NULL
int count = 0
list result = []
bytes data_class
try:
self.handle_error(lockdownd_get_sync_data_classes(self._c_client, &classes, &count))
for i from 0 <= i < count:
data_class = classes[i]
result.append(data_class)
return result
except Exception, e:
raise
finally:
if classes != NULL:
lockdownd_data_classes_free(classes)
cdef inline int16_t _send(self, plist.plist_t node):
return lockdownd_send(self._c_client, node)
cdef inline int16_t _receive(self, plist.plist_t* node):
return lockdownd_receive(self._c_client, node)
cdef inline BaseError _error(self, int16_t ret):
return LockdownError(ret)
|