lockdown.pxi 14 KB

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