Merge branch 'master' into openssl

This commit is contained in:
Jackson Coxson
2025-11-17 11:01:54 -07:00
47 changed files with 270 additions and 246 deletions

View File

@@ -2,7 +2,7 @@
name = "idevice"
description = "A Rust library to interact with services on iOS devices."
authors = ["Jackson Coxson"]
version = "0.1.47"
version = "0.1.48"
edition = "2024"
license = "MIT"
documentation = "https://docs.rs/idevice"

View File

@@ -1,4 +1,6 @@
#![doc = include_str!("../README.md")]
#![warn(missing_debug_implementations)]
#![warn(missing_copy_implementations)]
// Jackson Coxson
#[cfg(all(feature = "pair", feature = "rustls"))]
@@ -130,6 +132,7 @@ pub type IdeviceSocket = Box<dyn ReadWrite>;
///
/// Manages the connection socket and provides methods for common device operations
/// and message exchange.
#[derive(Debug)]
pub struct Idevice {
/// The underlying connection socket, boxed for dynamic dispatch
socket: Option<Box<dyn ReadWrite>>,

View File

@@ -7,6 +7,7 @@ use tokio::io::{AsyncRead, AsyncSeek, AsyncWrite};
use super::inner_file::InnerFileDescriptor;
use crate::IdeviceError;
#[derive(Debug)]
pub struct FileDescriptor<'a> {
inner: Pin<Box<InnerFileDescriptor<'a>>>,
}

View File

@@ -22,6 +22,7 @@ fn chunk_number(n: usize, chunk_size: usize) -> impl Iterator<Item = usize> {
}
// Used to descripe what the future returns
#[derive(Debug)]
pub(crate) enum PendingResult {
// writing
Empty,
@@ -368,6 +369,16 @@ impl AsyncSeek for InnerFileDescriptor<'_> {
}
}
impl std::fmt::Debug for InnerFileDescriptor<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("InnerFileDescriptor")
.field("client", &self.client)
.field("fd", &self.fd)
.field("path", &self.path)
.finish()
}
}
#[cfg(test)]
mod tests {
use std::sync::Arc;

View File

@@ -23,6 +23,7 @@ pub mod packet;
pub const MAGIC: u64 = 0x4141504c36414643;
/// Client for interacting with the AFC service on iOS devices
#[derive(Debug)]
pub struct AfcClient {
/// The underlying iDevice connection
pub idevice: Idevice,

View File

@@ -1,6 +1,6 @@
// Jackson Coxson
#[derive(Clone, Debug, PartialEq, Eq)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(u64)]
pub enum AfcOpcode {
Status = 0x00000001,
@@ -36,6 +36,7 @@ pub enum AfcOpcode {
}
#[repr(u64)]
#[derive(Clone, Copy, Debug)]
pub enum AfcFopenMode {
RdOnly = 0x00000001, // r O_RDONLY
Rw = 0x00000002, // r+ O_RDWR | O_CREAT
@@ -46,6 +47,7 @@ pub enum AfcFopenMode {
}
#[repr(u64)]
#[derive(Clone, Copy, Debug)]
pub enum LinkType {
Hardlink = 0x00000001,
Symlink = 0x00000002,

View File

@@ -6,7 +6,7 @@ use crate::{Idevice, IdeviceError};
use super::opcode::AfcOpcode;
#[derive(Clone, Debug)]
#[derive(Clone, Copy, Debug)]
pub struct AfcPacketHeader {
pub magic: u64,
pub entire_len: u64,
@@ -32,7 +32,7 @@ impl AfcPacketHeader {
res.extend_from_slice(&self.entire_len.to_le_bytes());
res.extend_from_slice(&self.header_payload_len.to_le_bytes());
res.extend_from_slice(&self.packet_num.to_le_bytes());
res.extend_from_slice(&(self.operation.clone() as u64).to_le_bytes());
res.extend_from_slice(&(self.operation as u64).to_le_bytes());
res
}

View File

@@ -3,6 +3,7 @@
use crate::{Idevice, IdeviceError, IdeviceService, obf};
/// Client for interacting with the AMFI service on the device
#[derive(Debug)]
pub struct AmfiClient {
/// The underlying device connection with established amfi service
pub idevice: Idevice,

View File

@@ -13,6 +13,7 @@ use crate::{Idevice, IdeviceError, IdeviceService, obf};
/// You must have the Bluetooth profile installed, or you'll get no data.
///
/// ``https://developer.apple.com/bug-reporting/profiles-and-logs/?name=bluetooth``
#[derive(Debug)]
pub struct BtPacketLoggerClient {
/// The underlying device connection with established logger service
pub idevice: Idevice,

View File

@@ -4,10 +4,12 @@ use tracing::warn;
use crate::{Idevice, IdeviceError, IdeviceService, RsdService, obf};
#[derive(Debug)]
pub struct CompanionProxy {
idevice: Idevice,
}
#[derive(Debug)]
pub struct CompanionProxyStream {
proxy: CompanionProxy,
}

View File

@@ -19,6 +19,7 @@ impl RsdService for AppServiceClient<Box<dyn ReadWrite>> {
}
}
#[derive(Debug)]
pub struct AppServiceClient<R: ReadWrite> {
inner: CoreDeviceServiceClient<R>,
}

View File

@@ -19,6 +19,7 @@ impl RsdService for DiagnostisServiceClient<Box<dyn ReadWrite>> {
}
}
#[derive(Debug)]
pub struct DiagnostisServiceClient<R: ReadWrite> {
inner: super::CoreDeviceServiceClient<R>,
}
@@ -70,3 +71,12 @@ impl<R: ReadWrite> DiagnostisServiceClient<R> {
}
}
}
impl std::fmt::Debug for SysdiagnoseResponse<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SysdiagnoseResponse")
.field("preferred_filename", &self.preferred_filename)
.field("expected_length", &self.expected_length)
.finish()
}
}

View File

@@ -17,6 +17,7 @@ pub use openstdiosocket::*;
const CORE_SERVICE_VERSION: &str = "443.18";
#[derive(Debug)]
pub struct CoreDeviceServiceClient<R: ReadWrite> {
inner: RemoteXpcClient<R>,
}

View File

@@ -16,6 +16,7 @@ impl RsdService for OpenStdioSocketClient {
/// Call ``read_uuid`` to get the UUID. Pass that to app service launch to connect to the stream of
/// the launched app. Inner is exposed to read and write to, using Tokio's AsyncReadExt/AsyncWriteExt
#[derive(Debug)]
pub struct OpenStdioSocketClient {
pub inner: Box<dyn ReadWrite>,
}

View File

@@ -82,6 +82,7 @@ impl CDTunnelPacket {
/// A high-level client for the `com.apple.internal.devicecompute.CoreDeviceProxy` service.
///
/// Handles session negotiation, handshake, and tunnel communication.
#[derive(Debug)]
pub struct CoreDeviceProxy {
/// The underlying idevice connection used for communication.
pub idevice: Idevice,

View File

@@ -15,6 +15,7 @@ use crate::{Idevice, IdeviceError, IdeviceService, afc::AfcClient, lockdown::Loc
///
/// This client wraps access to the `com.apple.crashreportcopymobile` service,
/// which exposes crash logs through the Apple File Conduit (AFC).
#[derive(Debug)]
pub struct CrashReportCopyMobileClient {
/// The underlying AFC client connected to the crash logs directory.
pub afc_client: AfcClient,

View File

@@ -27,6 +27,7 @@ impl RsdService for DebugProxyClient<Box<dyn ReadWrite>> {
///
/// Implements the GDB Remote Serial Protocol for communicating with debugserver
/// on iOS devices. Handles packet formatting, checksums, and acknowledgments.
#[derive(Debug)]
pub struct DebugProxyClient<R: ReadWrite> {
/// The underlying socket connection to debugproxy
pub socket: R,
@@ -38,6 +39,7 @@ pub struct DebugProxyClient<R: ReadWrite> {
///
/// Commands follow the GDB Remote Serial Protocol format:
/// $<command>[<hex-encoded args>]#<checksum>
#[derive(Debug)]
pub struct DebugserverCommand {
/// The command name (e.g. "qSupported", "vCont")
pub name: String,

View File

@@ -3,6 +3,7 @@
use crate::{Idevice, IdeviceError, IdeviceService, obf};
/// Client for interacting with the Diagnostics Relay
#[derive(Debug)]
pub struct DiagnosticsRelayClient {
/// The underlying device connection with established service
pub idevice: Idevice,

View File

@@ -46,6 +46,7 @@ use crate::{
};
/// A client for the location simulation service
#[derive(Debug)]
pub struct LocationSimulationClient<'a, R: ReadWrite> {
/// The underlying channel used for communication
channel: Channel<'a, R>,

View File

@@ -66,7 +66,7 @@ use crate::{IdeviceError, pretty_print_plist};
/// Message header containing metadata about the message
///
/// 32-byte structure that appears at the start of every message
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct MessageHeader {
/// Magic number identifying the protocol (0x1F3D5B79)
magic: u32,
@@ -91,7 +91,7 @@ pub struct MessageHeader {
/// Payload header containing information about the message contents
///
/// 16-byte structure following the message header
#[derive(Debug, Default, Clone, PartialEq)]
#[derive(Debug, Default, Clone, Copy, PartialEq)]
pub struct PayloadHeader {
/// Flags controlling message processing
flags: u32,
@@ -104,7 +104,7 @@ pub struct PayloadHeader {
/// Header for auxiliary data section
///
/// 16-byte structure preceding auxiliary data
#[derive(Debug, Default, PartialEq)]
#[derive(Debug, Default, Clone, Copy, PartialEq)]
pub struct AuxHeader {
/// Buffer size hint (often 496)
buffer_size: u32,

View File

@@ -23,6 +23,7 @@ pub struct NotificationInfo {
state_description: String,
}
#[derive(Debug)]
pub struct NotificationsClient<'a, R: ReadWrite> {
/// The underlying channel used for communication
pub channel: Channel<'a, R>,

View File

@@ -45,6 +45,7 @@ use super::remote_server::{Channel, RemoteServerClient};
///
/// Provides methods for launching, killing, and managing processes through the
/// instruments protocol. Each instance maintains its own communication channel.
#[derive(Debug)]
pub struct ProcessControlClient<'a, R: ReadWrite> {
/// The underlying channel for communication
channel: Channel<'a, R>,

View File

@@ -66,6 +66,7 @@ pub const INSTRUMENTS_MESSAGE_TYPE: u32 = 2;
///
/// Manages multiple communication channels and handles message serialization/deserialization.
/// Each channel operates independently and maintains its own message queue.
#[derive(Debug)]
pub struct RemoteServerClient<R: ReadWrite> {
/// The underlying device connection
idevice: R,
@@ -80,6 +81,7 @@ pub struct RemoteServerClient<R: ReadWrite> {
/// Handle to a specific communication channel
///
/// Provides channel-specific operations for use on the remote server client.
#[derive(Debug)]
pub struct Channel<'a, R: ReadWrite> {
/// Reference to parent client
client: &'a mut RemoteServerClient<R>,

View File

@@ -16,6 +16,7 @@ use crate::{
///
/// Provides methods for take screnn_shot through the
/// instruments protocol. Each instance maintains its own communication channel.
#[derive(Debug)]
pub struct ScreenshotClient<'a, R: ReadWrite> {
/// The underlying channel for communication
channel: Channel<'a, R>,

View File

@@ -12,6 +12,7 @@ use crate::{Idevice, IdeviceError, IdeviceService, obf};
/// Note that a running heartbeat client is required to access other services on the device.
/// Implements the standard "Marco-Polo" protocol
/// where the host sends "Polo" in response to the device's "Marco".
#[derive(Debug)]
pub struct HeartbeatClient {
/// The underlying device connection with established heartbeat service
pub idevice: Idevice,

View File

@@ -12,6 +12,7 @@ use super::afc::AfcClient;
///
/// HouseArrest is used to expose the container or Documents directory of an app to a host machine
/// over AFC (Apple File Conduit).
#[derive(Debug)]
pub struct HouseArrestClient {
/// The underlying device connection with the HouseArrest service
pub idevice: Idevice,

View File

@@ -14,6 +14,7 @@ use crate::{Idevice, IdeviceError, IdeviceService, obf};
///
/// This service provides access to information about installed applications
/// and can perform application management operations.
#[derive(Debug)]
pub struct InstallationProxyClient {
/// The underlying device connection with established installation_proxy service
pub idevice: Idevice,

View File

@@ -14,6 +14,7 @@ impl RsdService for InstallcoordinationProxy<Box<dyn ReadWrite>> {
}
}
#[derive(Debug)]
pub struct InstallcoordinationProxy<R: ReadWrite> {
inner: RemoteXpcClient<R>,
}

View File

@@ -14,6 +14,7 @@ use crate::{Idevice, IdeviceError, IdeviceService, obf, pairing_file};
/// - Access to device information and settings
/// - Service discovery and port allocation
/// - Session management and security
#[derive(Debug)]
pub struct LockdownClient {
/// The underlying device connection with established lockdown service
pub idevice: crate::Idevice,

View File

@@ -13,6 +13,7 @@ use crate::{Idevice, IdeviceError, IdeviceService, RsdService, obf};
/// - Installation of provisioning profiles
/// - Removal of provisioning profiles
/// - Querying installed profiles
#[derive(Debug)]
pub struct MisagentClient {
/// The underlying device connection with established misagent service
pub idevice: Idevice,

View File

@@ -22,6 +22,7 @@ use crate::tss::TSSRequest;
/// # Important Note
/// A lockdown client must be established and queried after establishing a mounter client,
/// or the device will stop responding to requests.
#[derive(Debug)]
pub struct ImageMounter {
/// The underlying device connection with established image mounter service
idevice: Idevice,

View File

@@ -6,6 +6,7 @@ use plist::Dictionary;
use crate::{Idevice, IdeviceError, IdeviceService, lockdown::LockdownClient, obf};
#[derive(Debug)]
pub struct MobileActivationdClient<'a> {
provider: &'a dyn crate::provider::IdeviceProvider,
}

View File

@@ -22,6 +22,7 @@ pub const DL_CODE_FILE_DATA: u8 = 0x0c;
///
/// This service provides access to device backup functionality including
/// creating backups, restoring from backups, and managing backup data.
#[derive(Debug)]
pub struct MobileBackup2Client {
/// The underlying device connection with established mobilebackup2 service
pub idevice: Idevice,
@@ -46,7 +47,7 @@ impl IdeviceService for MobileBackup2Client {
}
/// Backup message types used in the mobilebackup2 protocol
#[derive(Debug, Clone)]
#[derive(Debug, Clone, Copy)]
pub enum BackupMessageType {
/// Request to start a backup operation
BackupMessageTypeBackup,

View File

@@ -10,6 +10,7 @@ use tokio::io::AsyncWriteExt;
use crate::{Idevice, IdeviceError, IdeviceService, obf};
/// Client for interacting with the iOS device OsTraceRelay service
#[derive(Debug)]
pub struct OsTraceRelayClient {
/// The underlying device connection with established OsTraceRelay service
pub idevice: Idevice,
@@ -27,6 +28,7 @@ impl IdeviceService for OsTraceRelayClient {
}
/// An initialized client for receiving logs
#[derive(Debug)]
pub struct OsTraceRelayReceiver {
inner: OsTraceRelayClient,
}
@@ -48,7 +50,7 @@ pub struct SyslogLabel {
pub category: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Copy)]
pub enum LogLevel {
Notice = 0,
Info = 1,

View File

@@ -13,6 +13,7 @@ const ETHERNET_HEADER: &[u8] = &[
/// Client for interacting with the pcapd service on the device.
/// Note that this service only works over USB or through RSD.
#[derive(Debug)]
pub struct PcapdClient {
/// The underlying device connection with established service
pub idevice: Idevice,
@@ -220,6 +221,7 @@ impl<'a> ByteReader<'a> {
}
/// A writer for creating `.pcap` files from DevicePackets without external dependencies.
#[derive(Debug)]
pub struct PcapFileWriter<W: AsyncWrite + Unpin> {
writer: W,
}

View File

@@ -3,6 +3,7 @@
use crate::{Idevice, IdeviceError, IdeviceService, RsdService, obf};
/// Client for interacting with the preboard service on the device.
#[derive(Debug)]
pub struct PreboardServiceClient {
/// The underlying device connection with established service
pub idevice: Idevice,

View File

@@ -6,6 +6,7 @@ use tracing::warn;
use crate::{IdeviceError, ReadWrite, RemoteXpcClient, RsdService, obf};
/// Client for interacting with the Restore Service
#[derive(Debug)]
pub struct RestoreServiceClient {
/// The underlying device connection with established Restore Service service
pub stream: RemoteXpcClient<Box<dyn ReadWrite>>,

View File

@@ -7,10 +7,13 @@ use crate::{Idevice, IdeviceError, IdeviceService, obf};
use std::borrow::Cow;
use tokio::io::AsyncReadExt;
use tracing::{debug, warn};
#[derive(Debug)]
pub struct ScreenshotService {
/// Underlying device connection
pub idevice: Idevice,
}
impl IdeviceService for ScreenshotService {
fn service_name() -> Cow<'static, str> {
obf!("com.apple.mobile.screenshotr")

View File

@@ -1,5 +1,6 @@
use crate::{Idevice, IdeviceError, IdeviceService, obf};
#[derive(Debug)]
pub struct LocationSimulationService {
idevice: Idevice,
}

View File

@@ -9,6 +9,7 @@ use crate::{Idevice, IdeviceError, IdeviceService, obf};
///
/// This service provides access to home screen and app icon functionality,
/// such as retrieving app icons.
#[derive(Debug)]
pub struct SpringBoardServicesClient {
/// The underlying device connection with established SpringBoard services
pub idevice: Idevice,

View File

@@ -3,6 +3,7 @@
use crate::{Idevice, IdeviceError, IdeviceService, obf};
/// Client for interacting with the iOS device SyslogRelay service
#[derive(Debug)]
pub struct SyslogRelayClient {
/// The underlying device connection with established SyslogRelay service
pub idevice: Idevice,

View File

@@ -12,6 +12,7 @@ use tokio::{
};
use tracing::debug;
#[derive(Clone, Copy, Debug)]
pub enum ProtocolNumber {
Tcp = 6,
}

View File

@@ -16,7 +16,7 @@ pub struct ListDevicesResponse {
pub device_list: Vec<DeviceListResponse>,
}
#[derive(Deserialize)]
#[derive(Clone, Debug, Deserialize)]
pub struct DeviceListResponse {
#[serde(rename = "DeviceID")]
pub device_id: u32,
@@ -24,7 +24,7 @@ pub struct DeviceListResponse {
pub properties: DevicePropertiesResponse,
}
#[derive(Deserialize)]
#[derive(Clone, Debug, Deserialize)]
pub struct DevicePropertiesResponse {
#[serde(rename = "ConnectionType")]
pub connection_type: String,

View File

@@ -55,6 +55,7 @@ pub enum UsbmuxdListenEvent {
}
/// Active connection to the usbmuxd service
#[derive(Debug)]
pub struct UsbmuxdConnection {
socket: Box<dyn ReadWrite>,
tag: u32,

View File

@@ -12,6 +12,7 @@ pub use frame::Setting;
const HTTP2_MAGIC: &[u8] = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n".as_bytes();
#[derive(Debug)]
pub struct Http2Client<R: ReadWrite> {
inner: R,
cache: HashMap<u32, VecDeque<Vec<u8>>>,

View File

@@ -17,6 +17,7 @@ pub use format::{Dictionary, XPCMessage, XPCObject};
const ROOT_CHANNEL: u32 = 1;
const REPLY_CHANNEL: u32 = 3;
#[derive(Debug)]
pub struct RemoteXpcClient<R: ReadWrite> {
h2_client: http2::Http2Client<R>,
root_id: u64,