rusty_libimobiledevice/services/
mobile_activation.rs

1// jkcoxson
2
3use std::ffi::CString;
4
5use crate::{
6    bindings as unsafe_bindings, error::MobileActivationError, idevice::Device,
7    services::lockdownd::LockdowndService,
8};
9
10use plist_plus::Plist;
11
12pub struct MobileActivationClient<'a> {
13    pub(crate) pointer: unsafe_bindings::mobileactivation_client_t,
14    phantom: std::marker::PhantomData<&'a Device>,
15}
16
17impl MobileActivationClient<'_> {
18    /// Creates a new mobile activation service connection to the device
19    /// The use of this function is unknown
20    /// # Arguments
21    /// * `device` - The device to create the service with
22    /// # Returns
23    /// The lockdownd service
24    ///
25    /// ***Verified:*** False
26    pub fn new(
27        device: &Device,
28        descriptor: LockdowndService,
29    ) -> Result<Self, MobileActivationError> {
30        let mut client = unsafe { std::mem::zeroed() };
31
32        let result = unsafe {
33            unsafe_bindings::mobileactivation_client_new(
34                device.pointer,
35                descriptor.pointer,
36                &mut client,
37            )
38        }
39        .into();
40
41        if result != MobileActivationError::Success {
42            return Err(result);
43        }
44
45        Ok(MobileActivationClient {
46            pointer: client,
47            phantom: std::marker::PhantomData,
48        })
49    }
50
51    /// Starts a mobile activation service connection to the device
52    /// # Arguments
53    /// * `device` - The device to create the service with
54    /// * `service_name` - The name of the service to start
55    /// # Returns
56    /// An afc service connection
57    ///
58    /// ***Verified:*** False
59    pub fn start_service(
60        device: &Device,
61        label: impl Into<String>,
62    ) -> Result<Self, MobileActivationError> {
63        let label_c_string = CString::new(label.into()).unwrap();
64        let mut client = unsafe { std::mem::zeroed() };
65
66        let result = unsafe {
67            unsafe_bindings::mobileactivation_client_start_service(
68                device.pointer,
69                &mut client,
70                label_c_string.as_ptr(),
71            )
72        }
73        .into();
74
75        if result != MobileActivationError::Success {
76            return Err(result);
77        }
78
79        Ok(MobileActivationClient {
80            pointer: client,
81            phantom: std::marker::PhantomData,
82        })
83    }
84
85    /// Gets the activation state of the device
86    /// # Arguments
87    /// *none*
88    /// # Returns
89    /// A plist with the results
90    ///
91    /// ***Verified:*** False
92    pub fn get_activation_state(&self) -> Result<Plist, MobileActivationError> {
93        let mut plist = unsafe { std::mem::zeroed() };
94
95        let result = unsafe {
96            unsafe_bindings::mobileactivation_get_activation_state(self.pointer, &mut plist)
97        }
98        .into();
99
100        if result != MobileActivationError::Success {
101            return Err(result);
102        }
103
104        Ok(plist.into())
105    }
106
107    /// Gets a session blob for the device requied for activation.
108    /// Requires an internet connection as it queries albert.apple.com for the value
109    /// # Arguments
110    /// *none*
111    /// # Returns
112    /// A plist with the activation session info
113    pub fn create_activation_session_info(&self) -> Result<Plist, MobileActivationError> {
114        let mut plist = unsafe { std::mem::zeroed() };
115
116        let result = unsafe {
117            unsafe_bindings::mobileactivation_create_activation_session_info(
118                self.pointer,
119                &mut plist,
120            )
121        }
122        .into();
123
124        if result != MobileActivationError::Success {
125            return Err(result);
126        }
127
128        Ok(plist.into())
129    }
130
131    /// Gets the activation info from Apple's servers
132    /// # Arguments
133    /// *none*
134    /// # Returns
135    /// Both the handshake reponse and the activation info
136    ///
137    /// ***Verified:*** False
138    pub fn create_activation_info_with_session(
139        &self,
140    ) -> Result<(Plist, Plist), MobileActivationError> {
141        let plist = unsafe { std::mem::zeroed() };
142        let mut session_plist = unsafe { std::mem::zeroed() };
143
144        let result = unsafe {
145            unsafe_bindings::mobileactivation_create_activation_info_with_session(
146                self.pointer,
147                plist,
148                &mut session_plist,
149            )
150        }
151        .into();
152
153        if result != MobileActivationError::Success {
154            return Err(result);
155        }
156
157        Ok((plist.into(), session_plist.into()))
158    }
159
160    /// Activates a device
161    /// # Arguments
162    /// * `record` - A plist containing the activation record fetched from Apple
163    /// * `session` - A plist containing session blobs. Pass None if not required.
164    /// # Returns
165    /// *none*
166    ///
167    /// ***Verified:*** False
168    pub fn activate(
169        &self,
170        record: Plist,
171        session: Option<Plist>,
172    ) -> Result<(), MobileActivationError> {
173        let result = unsafe {
174            if let Some(session) = session {
175                unsafe_bindings::mobileactivation_activate_with_session(
176                    self.pointer,
177                    record.get_pointer(),
178                    session.get_pointer(),
179                )
180            } else {
181                unsafe_bindings::mobileactivation_activate(self.pointer, record.get_pointer())
182            }
183        }
184        .into();
185
186        if result != MobileActivationError::Success {
187            return Err(result);
188        }
189
190        Ok(())
191    }
192
193    /// Deactivates a device, requiring it to be reactivated by Apple's servers
194    /// # Arguments
195    /// *none*
196    /// # Returns
197    /// *none*
198    ///
199    /// ***Verified:*** False
200    pub fn deactivate(&self) -> Result<(), MobileActivationError> {
201        let result = unsafe { unsafe_bindings::mobileactivation_deactivate(self.pointer) }.into();
202
203        if result != MobileActivationError::Success {
204            return Err(result);
205        }
206
207        Ok(())
208    }
209}
210
211impl Drop for MobileActivationClient<'_> {
212    fn drop(&mut self) {
213        unsafe {
214            unsafe_bindings::mobileactivation_client_free(self.pointer);
215        }
216    }
217}