diff options
Diffstat (limited to 'cython/lockdown.pxi')
-rw-r--r-- | cython/lockdown.pxi | 351 |
1 files changed, 351 insertions, 0 deletions
diff --git a/cython/lockdown.pxi b/cython/lockdown.pxi new file mode 100644 index 0000000..25edb4c --- /dev/null +++ b/cython/lockdown.pxi @@ -0,0 +1,351 @@ +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 = NULL + char* c_domain = NULL + char* c_key = NULL + + c_node = plist.native_to_plist_t(value) + if domain is not None: + c_domain = domain + if key is not None: + c_key = key + try: + self.handle_error(lockdownd_set_value(self._c_client, c_domain, c_key, c_node)) + except BaseError, e: + raise + finally: + if c_node != NULL: + c_node = NULL + + 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_str = service.__service_name__.encode('utf-8') + elif isinstance(service, (str, bytes)): + c_service_name_str = service.encode('utf-8') + else: + raise TypeError("LockdownClient.start_service() takes a BaseService or string as its first argument") + c_service_name = c_service_name_str + + 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) |