mirror of
https://github.com/StikDebug/StikDebug.git
synced 2026-10-16 04:20:30 +00:00
Add Developer Disk Image Mounting
This commit is contained in:
parent
b605e9d7cc
commit
b0738cd349
7 changed files with 808 additions and 28 deletions
|
|
@ -34,7 +34,7 @@ StikJIT **does not collect or store any user data.**
|
|||
- [X] Integrate [`em_proxy`](https://github.com/SideStore/em_proxy)
|
||||
- [X] Compile [`idevice`](https://github.com/jkcoxson/idevice)
|
||||
- [X] Implement heartbeat
|
||||
- [ ] Mount the developer image
|
||||
- [X] Mount the developer image
|
||||
- [X] Retrieve and filter installed apps by `get-task-allow`
|
||||
- [X] Enable JIT for selected apps
|
||||
- [X] Design and implement a user-friendly UI *(Done for now)*
|
||||
|
|
|
|||
|
|
@ -15,6 +15,21 @@ struct HeartbeatApp: App {
|
|||
@State private var isPairing = false
|
||||
@State private var heartBeat = false
|
||||
@State private var error: Int32? = nil
|
||||
@StateObject private var mount = MountingProgress.shared
|
||||
|
||||
let urls: [String] = [
|
||||
"https://github.com/doronz88/DeveloperDiskImage/raw/refs/heads/main/PersonalizedImages/Xcode_iOS_DDI_Personalized/BuildManifest.plist",
|
||||
"https://github.com/doronz88/DeveloperDiskImage/raw/refs/heads/main/PersonalizedImages/Xcode_iOS_DDI_Personalized/Image.dmg",
|
||||
"https://github.com/doronz88/DeveloperDiskImage/raw/refs/heads/main/PersonalizedImages/Xcode_iOS_DDI_Personalized/Image.dmg.trustcache"
|
||||
]
|
||||
|
||||
let outputDir: String = "DDI"
|
||||
|
||||
let outputFiles: [String] = [
|
||||
"DDI/BuildManifest.plist",
|
||||
"DDI/Image.dmg",
|
||||
"DDI/Image.dmg.trustcache"
|
||||
]
|
||||
|
||||
init() {
|
||||
let fixMethod = class_getInstanceMethod(UIDocumentPickerViewController.self, #selector(UIDocumentPickerViewController.fix_init(forOpeningContentTypes:asCopy:)))!
|
||||
|
|
@ -30,7 +45,7 @@ struct HeartbeatApp: App {
|
|||
startProxy()
|
||||
if FileManager.default.fileExists(atPath: URL.documentsDirectory.appendingPathComponent("pairingFile.plist").path) {
|
||||
Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { timer in
|
||||
if heartBeat {
|
||||
if pubHeartBeat {
|
||||
isLoading = false
|
||||
timer.invalidate()
|
||||
} else {
|
||||
|
|
@ -82,6 +97,17 @@ struct HeartbeatApp: App {
|
|||
}
|
||||
} else {
|
||||
MainTabView()
|
||||
.onAppear() {
|
||||
let fileManager = FileManager.default
|
||||
for (index, urlString) in urls.enumerated() {
|
||||
let destinationURL = URL.documentsDirectory.appendingPathComponent(outputFiles[index])
|
||||
if !fileManager.fileExists(atPath: destinationURL.path) {
|
||||
downloadFile(from: urlString, to: destinationURL)
|
||||
}
|
||||
}
|
||||
|
||||
mount.pubMount()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -103,41 +129,86 @@ struct HeartbeatApp: App {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func startHeartbeatInBackground() {
|
||||
let heartBeat = Thread {
|
||||
let completionHandler: @convention(block) (Int32, String?) -> Void = { result, message in
|
||||
}
|
||||
|
||||
if result == 0 {
|
||||
print("Heartbeat started successfully: \(message ?? "")")
|
||||
|
||||
self.heartBeat = true
|
||||
var pubHeartBeat = false
|
||||
|
||||
actor FunctionGuard<T> {
|
||||
private var runningTask: Task<T, Never>?
|
||||
|
||||
func execute(_ work: @escaping @Sendable () -> T) async -> T {
|
||||
if let task = runningTask {
|
||||
return await task.value // If already running, wait for the existing result
|
||||
}
|
||||
|
||||
let task = Task.detached { work() } // Run in the background
|
||||
runningTask = task
|
||||
let result = await task.value
|
||||
runningTask = nil
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
class MountingProgress: ObservableObject {
|
||||
static var shared = MountingProgress()
|
||||
@Published var mountProgress: Double = 0.0
|
||||
@Published var mountingThread: Thread?
|
||||
@Published var coolisMounted: Bool = false
|
||||
|
||||
func checkforMounted() {
|
||||
DispatchQueue.main.async {
|
||||
self.coolisMounted = isMounted()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func pubMount() { mount() }
|
||||
|
||||
private func mount() {
|
||||
self.coolisMounted = isMounted()
|
||||
|
||||
let fileManager = FileManager.default
|
||||
let pairingpath = URL.documentsDirectory.appendingPathComponent("pairingFile.plist").path
|
||||
|
||||
if pubHeartBeat, fileManager.fileExists(atPath: pairingpath), !isMounted() {
|
||||
if let mountingThread {
|
||||
mountingThread.cancel()
|
||||
self.mountingThread = nil
|
||||
}
|
||||
|
||||
mountingThread = Thread {
|
||||
let mount = mountPersonalDDI(imagePath: URL.documentsDirectory.appendingPathComponent("DDI/Image.dmg").path, trustcachePath: URL.documentsDirectory.appendingPathComponent("DDI/Image.dmg.trustcache").path, manifestPath: URL.documentsDirectory.appendingPathComponent("DDI/BuildManifest.plist").path, pairingFilePath: pairingpath)
|
||||
|
||||
if !mount {
|
||||
showAlert(title: "Error", message: "An Error Occured when Mounting the DDI", showOk: true, showTryAgain: true) { cool in
|
||||
if cool {
|
||||
self.mount()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
print("Error: \(result == InvalidHostID.rawValue ? "Invalid host ID, Please Selecr New Pairing File" : message ?? "") (Code: \(result))")
|
||||
|
||||
showAlert(title: "HeartBeat Error", message: "\(message ?? "") (\(result))", showOk: true) { _ in
|
||||
self.error = result
|
||||
DispatchQueue.main.async {
|
||||
self.coolisMounted = isMounted()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JITEnableContext.shared().startHeartbeat(completionHandler: completionHandler, logger: nil)
|
||||
mountingThread!.qualityOfService = .background
|
||||
mountingThread!.name = "mounting"
|
||||
mountingThread!.start()
|
||||
}
|
||||
|
||||
heartBeat.qualityOfService = .background
|
||||
heartBeat.name = "HeartBeat"
|
||||
heartBeat.start()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
func startHeartbeatInBackground() {
|
||||
let heartBeat = Thread {
|
||||
let completionHandler: @convention(block) (Int32, String?) -> Void = { result, message in
|
||||
|
||||
if result == 0 {
|
||||
print("Heartbeat started successfully: \(message ?? "")")
|
||||
|
||||
pubHeartBeat = true
|
||||
} else {
|
||||
print("Error: \(message ?? "") (Code: \(result))")
|
||||
|
||||
|
|
@ -199,22 +270,65 @@ struct LoadingView: View {
|
|||
}
|
||||
}
|
||||
|
||||
public func showAlert(title: String, message: String, showOk: Bool, completion: @escaping (Bool) -> Void) {
|
||||
public func showAlert(title: String, message: String, showOk: Bool, showTryAgain: Bool = false, completion: @escaping (Bool) -> Void) {
|
||||
DispatchQueue.main.async {
|
||||
if let mainWindow = UIApplication.shared.windows.last {
|
||||
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
|
||||
|
||||
if showOk {
|
||||
if showOk, !showTryAgain {
|
||||
let okAction = UIAlertAction(title: "OK", style: .default) { _ in
|
||||
completion(true)
|
||||
}
|
||||
|
||||
alert.addAction(okAction)
|
||||
} else {
|
||||
} else if !showTryAgain {
|
||||
completion(false)
|
||||
}
|
||||
|
||||
if showTryAgain {
|
||||
let tryAgainAction = UIAlertAction(title: "Try Again", style: .default) { _ in
|
||||
completion(true)
|
||||
}
|
||||
|
||||
alert.addAction(tryAgainAction)
|
||||
|
||||
let okAction = UIAlertAction(title: "OK", style: .cancel) { _ in
|
||||
completion(false)
|
||||
}
|
||||
|
||||
alert.addAction(okAction)
|
||||
}
|
||||
|
||||
mainWindow.rootViewController?.present(alert, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func downloadFile(from urlString: String, to destinationURL: URL) {
|
||||
let fileManager = FileManager.default
|
||||
let documentsDirectory = URL.documentsDirectory
|
||||
|
||||
|
||||
guard let url = URL(string: urlString) else {
|
||||
print("Invalid URL: \(urlString)")
|
||||
return
|
||||
}
|
||||
|
||||
let task = URLSession.shared.downloadTask(with: url) { (tempLocalUrl, response, error) in
|
||||
guard let tempLocalUrl = tempLocalUrl, error == nil else {
|
||||
print("Error downloading file from \(urlString): \(String(describing: error))")
|
||||
return
|
||||
}
|
||||
|
||||
do {
|
||||
// Move the downloaded file to the destination
|
||||
try fileManager.createDirectory(at: destinationURL.deletingLastPathComponent(), withIntermediateDirectories: true, attributes: nil)
|
||||
try fileManager.moveItem(at: tempLocalUrl, to: destinationURL)
|
||||
print("Downloaded \(urlString) to \(destinationURL.path)")
|
||||
} catch {
|
||||
print("Error saving file: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
task.resume()
|
||||
}
|
||||
|
|
|
|||
225
StikJIT/Utilities/mountDDI.swift
Normal file
225
StikJIT/Utilities/mountDDI.swift
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
//
|
||||
// mountDDI.swift
|
||||
// StikJIT
|
||||
//
|
||||
// Created by Stossy11 on 29/03/2025.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
typealias IdevicePairingFile = OpaquePointer
|
||||
typealias TcpProviderHandle = OpaquePointer
|
||||
typealias CoreDeviceProxyHandle = OpaquePointer
|
||||
typealias AdapterHandle = OpaquePointer
|
||||
typealias ImageMounterHandle = OpaquePointer
|
||||
typealias LockdowndClientHandle = OpaquePointer
|
||||
|
||||
func progressCallback(progress: size_t, total: size_t, context: UnsafeMutableRawPointer?) {
|
||||
let percentage = Double(progress) / Double(total) * 100.0
|
||||
print("Mounting progress: \(percentage)%")
|
||||
|
||||
MountingProgress.shared.mountProgress = percentage
|
||||
}
|
||||
|
||||
func readFile(path: String) -> Data? {
|
||||
guard let file = fopen(path, "rb") else {
|
||||
perror("Failed to open file")
|
||||
return nil
|
||||
}
|
||||
|
||||
fseek(file, 0, SEEK_END)
|
||||
let fileSize = ftell(file)
|
||||
fseek(file, 0, SEEK_SET)
|
||||
|
||||
guard fileSize > 0 else {
|
||||
fclose(file)
|
||||
return nil
|
||||
}
|
||||
|
||||
var buffer = Data(count: fileSize)
|
||||
buffer.withUnsafeMutableBytes { ptr in
|
||||
fread(ptr.baseAddress, 1, fileSize, file)
|
||||
}
|
||||
|
||||
fclose(file)
|
||||
return buffer
|
||||
}
|
||||
|
||||
func htons(_ value: UInt16) -> UInt16 {
|
||||
return CFSwapInt16HostToBig(value)
|
||||
}
|
||||
|
||||
func isMounted() -> Bool {
|
||||
var addr = sockaddr_in()
|
||||
memset(&addr, 0, MemoryLayout<sockaddr_in>.size)
|
||||
addr.sin_family = sa_family_t(AF_INET)
|
||||
addr.sin_port = htons(UInt16(LOCKDOWN_PORT))
|
||||
let sockaddrPointer = UnsafeRawPointer(&addr).bindMemory(to: sockaddr.self, capacity: 1)
|
||||
|
||||
let pairingFilePath = URL.documentsDirectory.appendingPathComponent("pairingFile.plist").path
|
||||
|
||||
guard inet_pton(AF_INET, "10.7.0.1", &addr.sin_addr) == 1 else {
|
||||
print("Invalid IP address")
|
||||
return false
|
||||
}
|
||||
|
||||
// Read pairing file
|
||||
var pairingFile: IdevicePairingFile?
|
||||
let err = idevice_pairing_file_read(pairingFilePath, &pairingFile)
|
||||
if err != IdeviceSuccess {
|
||||
print("Failed to read pairing file: \(err)")
|
||||
return false
|
||||
}
|
||||
|
||||
// Create TCP provider
|
||||
var provider: TcpProviderHandle?
|
||||
let providerError = idevice_tcp_provider_new(sockaddrPointer, pairingFile, "ImageMounterTest", &provider)
|
||||
if providerError != IdeviceSuccess {
|
||||
print("Failed to create TCP provider: \(providerError)")
|
||||
return false
|
||||
}
|
||||
|
||||
// Connect to image mounter
|
||||
var client: ImageMounterHandle?
|
||||
let connectError = image_mounter_connect_tcp(provider, &client)
|
||||
if connectError != IdeviceSuccess {
|
||||
print("Failed to connect to image mounter: \(connectError)")
|
||||
return false
|
||||
}
|
||||
tcp_provider_free(provider)
|
||||
|
||||
print("wow")
|
||||
|
||||
var devices: UnsafeMutableRawPointer?
|
||||
var devicesLen: size_t = 0
|
||||
let listError = image_mounter_copy_devices(client, &devices, &devicesLen)
|
||||
if listError == IdeviceSuccess {
|
||||
let deviceList = devices?.assumingMemoryBound(to: plist_t.self)
|
||||
var devices: [String] = []
|
||||
for i in 0..<devicesLen {
|
||||
let device = deviceList?[i]
|
||||
var xmlData: UnsafeMutablePointer<CChar>?
|
||||
var xmlLength: Int32 = 0
|
||||
|
||||
// Use libplist function to convert to XML
|
||||
plist_to_xml(device, &xmlData, &xmlLength)
|
||||
if let xml = xmlData {
|
||||
devices.append("\(xml)")
|
||||
}
|
||||
plist_mem_free(xmlData)
|
||||
plist_free(device)
|
||||
}
|
||||
|
||||
image_mounter_free(client)
|
||||
return devices.count != 0
|
||||
} else {
|
||||
print("Failed to get device list: \(listError)")
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func mountPersonalDDI(deviceIP: String = "10.7.0.1", imagePath: String, trustcachePath: String, manifestPath: String, pairingFilePath: String) -> Bool {
|
||||
idevice_init_logger(Debug, Disabled, nil)
|
||||
|
||||
print("Mounting \(imagePath) \(trustcachePath) \(manifestPath)")
|
||||
|
||||
guard let image = readFile(path: imagePath),
|
||||
let trustcache = readFile(path: trustcachePath),
|
||||
let buildManifest = readFile(path: manifestPath) else {
|
||||
print("Failed to read one or more files")
|
||||
return false
|
||||
}
|
||||
|
||||
var addr = sockaddr_in()
|
||||
memset(&addr, 0, MemoryLayout<sockaddr_in>.size)
|
||||
addr.sin_family = sa_family_t(AF_INET)
|
||||
addr.sin_port = htons(UInt16(LOCKDOWN_PORT))
|
||||
let sockaddrPointer = UnsafeRawPointer(&addr).bindMemory(to: sockaddr.self, capacity: 1)
|
||||
|
||||
guard inet_pton(AF_INET, deviceIP, &addr.sin_addr) == 1 else {
|
||||
print("Invalid IP address")
|
||||
return false
|
||||
}
|
||||
|
||||
var pairingFile: IdevicePairingFile?
|
||||
let err = idevice_pairing_file_read(pairingFilePath.cString(using: .utf8), &pairingFile)
|
||||
if err != IdeviceSuccess {
|
||||
print("Failed to read pairing file: \(err)")
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
var provider: TcpProviderHandle?
|
||||
let providerError = idevice_tcp_provider_new(sockaddrPointer, pairingFile, "ImageMounterTest".cString(using: .utf8), &provider)
|
||||
if providerError != IdeviceSuccess {
|
||||
print("Failed to create TCP provider: \(providerError)")
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
var pairingFile2: IdevicePairingFile?
|
||||
let P2err = idevice_pairing_file_read(pairingFilePath.cString(using: .utf8), &pairingFile2)
|
||||
if P2err != IdeviceSuccess {
|
||||
print("Failed to read pairing file: \(err)")
|
||||
return false
|
||||
}
|
||||
|
||||
var lockdownClient: LockdowndClientHandle?
|
||||
guard lockdownd_connect_tcp(provider, &lockdownClient) == IdeviceSuccess else {
|
||||
print("Failed to connect to lockdownd")
|
||||
return false
|
||||
}
|
||||
|
||||
guard lockdownd_start_session(lockdownClient, pairingFile2) == IdeviceSuccess else {
|
||||
print("Failed to start session")
|
||||
return false
|
||||
}
|
||||
|
||||
var uniqueChipIDPlist: plist_t?
|
||||
guard lockdownd_get_value(lockdownClient, "UniqueChipID".cString(using: .utf8), &uniqueChipIDPlist) == IdeviceSuccess else {
|
||||
print("Failed to get UniqueChipID")
|
||||
return false
|
||||
}
|
||||
|
||||
var uniqueChipID: UInt64 = 0
|
||||
plist_get_uint_val(uniqueChipIDPlist, &uniqueChipID)
|
||||
plist_free(uniqueChipIDPlist)
|
||||
print(uniqueChipID)
|
||||
|
||||
|
||||
var mounterClient: ImageMounterHandle?
|
||||
guard image_mounter_connect_tcp(provider, &mounterClient) == IdeviceSuccess else {
|
||||
print("Failed to connect to image mounter")
|
||||
return false
|
||||
}
|
||||
|
||||
let result = image.withUnsafeBytes { imagePtr in
|
||||
trustcache.withUnsafeBytes { trustcachePtr in
|
||||
buildManifest.withUnsafeBytes { manifestPtr in
|
||||
image_mounter_mount_personalized_tcp_with_callback(
|
||||
mounterClient,
|
||||
provider,
|
||||
imagePtr.baseAddress?.assumingMemoryBound(to: UInt8.self),
|
||||
image.count,
|
||||
trustcachePtr.baseAddress?.assumingMemoryBound(to: UInt8.self),
|
||||
trustcache.count,
|
||||
manifestPtr.baseAddress?.assumingMemoryBound(to: UInt8.self),
|
||||
buildManifest.count,
|
||||
nil,
|
||||
uniqueChipID,
|
||||
progressCallback,
|
||||
nil
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if result != IdeviceSuccess {
|
||||
print(result)
|
||||
print("Failed to mount personalized image")
|
||||
return false
|
||||
} else {
|
||||
print("Successfully mounted personalized image!")
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
@ -52,6 +52,14 @@ struct HomeView: View {
|
|||
|
||||
// Main action button - changes based on whether we have a pairing file
|
||||
Button(action: {
|
||||
|
||||
if !isMounted() {
|
||||
showAlert(title: "Device Not Mounted", message: "The Developer Disk Image has not been mounted yet. Check in settings for more information.", showOk: true) { cool in
|
||||
// No Need
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if pairingFileExists {
|
||||
// Got a pairing file, show apps
|
||||
isShowingInstalledApps = true
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ struct SettingsView: View {
|
|||
@State private var isImportingFile = false
|
||||
@State private var importProgress: Float = 0.0
|
||||
|
||||
@StateObject private var mountProg = MountingProgress.shared
|
||||
|
||||
// Developer profile image URLs
|
||||
private let developerProfiles: [String: String] = [
|
||||
"Blu": "https://github.com/0-Blu.png",
|
||||
|
|
@ -169,6 +171,61 @@ struct SettingsView: View {
|
|||
.padding(.horizontal, 16)
|
||||
}
|
||||
|
||||
SettingsCard {
|
||||
VStack(alignment: .leading, spacing: 20) {
|
||||
Text("Developer Disk Image")
|
||||
.font(.headline)
|
||||
.foregroundColor(.primary)
|
||||
.padding(.bottom, 4)
|
||||
|
||||
if mountProg.coolisMounted {
|
||||
HStack {
|
||||
Spacer()
|
||||
Text("✓ Developer Disk Image Mounted Sucessfully!")
|
||||
.font(.system(.callout, design: .rounded))
|
||||
.foregroundColor(.green)
|
||||
.padding(.vertical, 10)
|
||||
.padding(.horizontal, 18)
|
||||
.background(Color.green.opacity(0.1))
|
||||
.cornerRadius(10)
|
||||
Spacer()
|
||||
}
|
||||
.padding(.top, 6)
|
||||
} else {
|
||||
HStack {
|
||||
Text("Mounting Developer Disk Image...")
|
||||
.font(.system(.caption, design: .rounded))
|
||||
.foregroundColor(.secondary)
|
||||
Spacer()
|
||||
Text("\(Int(MountingProgress.shared.mountProgress))%")
|
||||
.font(.system(.caption, design: .rounded))
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
|
||||
GeometryReader { geometry in
|
||||
ZStack(alignment: .leading) {
|
||||
RoundedRectangle(cornerRadius: 6)
|
||||
.fill(Color(UIColor.tertiarySystemFill))
|
||||
.frame(height: 10)
|
||||
|
||||
RoundedRectangle(cornerRadius: 6)
|
||||
.fill(Color.green)
|
||||
.frame(width: geometry.size.width * CGFloat(MountingProgress.shared.mountProgress), height: 10)
|
||||
.animation(.linear(duration: 0.3), value: MountingProgress.shared.mountProgress)
|
||||
}
|
||||
}
|
||||
.frame(height: 10)
|
||||
}
|
||||
|
||||
}
|
||||
.padding(.vertical, 20)
|
||||
.padding(.horizontal, 16)
|
||||
.onAppear() {
|
||||
mountProg.checkforMounted()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// About section
|
||||
SettingsCard {
|
||||
VStack(alignment: .leading, spacing: 20) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
// Jackson Coxson
|
||||
// Bindings to idevice - https://github.com/jkcoxson/idevice
|
||||
|
||||
|
||||
#ifndef IDEVICE_H
|
||||
#define IDEVICE_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
|
@ -8,11 +12,9 @@
|
|||
#include <sys/socket.h>
|
||||
#include "plist.h"
|
||||
|
||||
#ifndef IDEVICE_H
|
||||
#define IDEVICE_H
|
||||
|
||||
#define LOCKDOWN_PORT 62078
|
||||
|
||||
|
||||
typedef enum IdeviceErrorCode {
|
||||
IdeviceSuccess = 0,
|
||||
Socket = -1,
|
||||
|
|
@ -102,6 +104,8 @@ typedef struct ImageMounterHandle ImageMounterHandle;
|
|||
|
||||
typedef struct InstallationProxyClientHandle InstallationProxyClientHandle;
|
||||
|
||||
typedef struct LockdowndClientHandle LockdowndClientHandle;
|
||||
|
||||
/**
|
||||
* Opaque handle to a ProcessControlClient
|
||||
*/
|
||||
|
|
@ -915,6 +919,145 @@ enum IdeviceErrorCode installation_proxy_get_apps(struct InstallationProxyClient
|
|||
*/
|
||||
void installation_proxy_client_free(struct InstallationProxyClientHandle *handle);
|
||||
|
||||
/**
|
||||
* Connects to lockdownd service using TCP provider
|
||||
*
|
||||
* # Arguments
|
||||
* * [`provider`] - A TcpProvider
|
||||
* * [`client`] - On success, will be set to point to a newly allocated LockdowndClient handle
|
||||
*
|
||||
* # Returns
|
||||
* An error code indicating success or failure
|
||||
*
|
||||
* # Safety
|
||||
* `provider` must be a valid pointer to a handle allocated by this library
|
||||
* `client` must be a valid, non-null pointer to a location where the handle will be stored
|
||||
*/
|
||||
enum IdeviceErrorCode lockdownd_connect_tcp(struct TcpProviderHandle *provider,
|
||||
struct LockdowndClientHandle **client);
|
||||
|
||||
/**
|
||||
* Connects to lockdownd service using Usbmuxd provider
|
||||
*
|
||||
* # Arguments
|
||||
* * [`provider`] - A UsbmuxdProvider
|
||||
* * [`client`] - On success, will be set to point to a newly allocated LockdowndClient handle
|
||||
*
|
||||
* # Returns
|
||||
* An error code indicating success or failure
|
||||
*
|
||||
* # Safety
|
||||
* `provider` must be a valid pointer to a handle allocated by this library
|
||||
* `client` must be a valid, non-null pointer to a location where the handle will be stored
|
||||
*/
|
||||
enum IdeviceErrorCode lockdownd_connect_usbmuxd(struct UsbmuxdProviderHandle *provider,
|
||||
struct LockdowndClientHandle **client);
|
||||
|
||||
/**
|
||||
* Creates a new LockdowndClient from an existing Idevice connection
|
||||
*
|
||||
* # Arguments
|
||||
* * [`socket`] - An IdeviceSocket handle
|
||||
* * [`client`] - On success, will be set to point to a newly allocated LockdowndClient handle
|
||||
*
|
||||
* # Returns
|
||||
* An error code indicating success or failure
|
||||
*
|
||||
* # Safety
|
||||
* `socket` must be a valid pointer to a handle allocated by this library
|
||||
* `client` must be a valid, non-null pointer to a location where the handle will be stored
|
||||
*/
|
||||
enum IdeviceErrorCode lockdownd_new(struct IdeviceHandle *socket,
|
||||
struct LockdowndClientHandle **client);
|
||||
|
||||
/**
|
||||
* Starts a session with lockdownd
|
||||
*
|
||||
* # Arguments
|
||||
* * `client` - A valid LockdowndClient handle
|
||||
* * `pairing_file` - An IdevicePairingFile alocated by this library
|
||||
*
|
||||
* # Returns
|
||||
* An error code indicating success or failure
|
||||
*
|
||||
* # Safety
|
||||
* `client` must be a valid pointer to a handle allocated by this library
|
||||
* `pairing_file` must be a valid plist_t containing a pairing file
|
||||
*/
|
||||
enum IdeviceErrorCode lockdownd_start_session(struct LockdowndClientHandle *client,
|
||||
struct IdevicePairingFile *pairing_file);
|
||||
|
||||
/**
|
||||
* Starts a service through lockdownd
|
||||
*
|
||||
* # Arguments
|
||||
* * `client` - A valid LockdowndClient handle
|
||||
* * `identifier` - The service identifier to start (null-terminated string)
|
||||
* * `port` - Pointer to store the returned port number
|
||||
* * `ssl` - Pointer to store whether SSL should be enabled
|
||||
*
|
||||
* # Returns
|
||||
* An error code indicating success or failure
|
||||
*
|
||||
* # Safety
|
||||
* `client` must be a valid pointer to a handle allocated by this library
|
||||
* `identifier` must be a valid null-terminated string
|
||||
* `port` and `ssl` must be valid pointers
|
||||
*/
|
||||
enum IdeviceErrorCode lockdownd_start_service(struct LockdowndClientHandle *client,
|
||||
const char *identifier,
|
||||
uint16_t *port,
|
||||
bool *ssl);
|
||||
|
||||
/**
|
||||
* Gets a value from lockdownd
|
||||
*
|
||||
* # Arguments
|
||||
* * `client` - A valid LockdowndClient handle
|
||||
* * `value` - The value to get (null-terminated string)
|
||||
* * `out_plist` - Pointer to store the returned plist value
|
||||
*
|
||||
* # Returns
|
||||
* An error code indicating success or failure
|
||||
*
|
||||
* # Safety
|
||||
* `client` must be a valid pointer to a handle allocated by this library
|
||||
* `value` must be a valid null-terminated string
|
||||
* `out_plist` must be a valid pointer to store the plist
|
||||
*/
|
||||
enum IdeviceErrorCode lockdownd_get_value(struct LockdowndClientHandle *client,
|
||||
const char *value,
|
||||
void **out_plist);
|
||||
|
||||
/**
|
||||
* Gets all values from lockdownd
|
||||
*
|
||||
* # Arguments
|
||||
* * `client` - A valid LockdowndClient handle
|
||||
* * `out_plist` - Pointer to store the returned plist dictionary
|
||||
*
|
||||
* # Returns
|
||||
* An error code indicating success or failure
|
||||
*
|
||||
* # Safety
|
||||
* `client` must be a valid pointer to a handle allocated by this library
|
||||
* `out_plist` must be a valid pointer to store the plist
|
||||
*/
|
||||
enum IdeviceErrorCode lockdownd_get_all_values(struct LockdowndClientHandle *client,
|
||||
void **out_plist);
|
||||
|
||||
/**
|
||||
* Frees a LockdowndClient handle
|
||||
*
|
||||
* # Arguments
|
||||
* * [`handle`] - The handle to free
|
||||
*
|
||||
* # Safety
|
||||
* `handle` must be a valid pointer to the handle that was allocated by this library,
|
||||
* or NULL (in which case this function does nothing)
|
||||
*/
|
||||
void lockdownd_client_free(struct LockdowndClientHandle *handle);
|
||||
|
||||
/**
|
||||
* Initializes the logger
|
||||
*
|
||||
|
|
@ -1153,6 +1296,239 @@ enum IdeviceErrorCode image_mounter_mount_developer(struct ImageMounterHandle *c
|
|||
const uint8_t *signature,
|
||||
size_t signature_len);
|
||||
|
||||
/**
|
||||
* Queries the personalization manifest from the device
|
||||
*
|
||||
* # Arguments
|
||||
* * [`client`] - A valid ImageMounter handle
|
||||
* * [`image_type`] - The type of image to query
|
||||
* * [`signature`] - Pointer to the signature data
|
||||
* * [`signature_len`] - Length of the signature data
|
||||
* * [`manifest`] - Will be set to point to the manifest data on success
|
||||
* * [`manifest_len`] - Will be set to the length of the manifest data
|
||||
*
|
||||
* # Returns
|
||||
* An error code indicating success or failure
|
||||
*
|
||||
* # Safety
|
||||
* All pointers must be valid and non-null
|
||||
* `image_type` must be a valid null-terminated C string
|
||||
*/
|
||||
enum IdeviceErrorCode image_mounter_query_personalization_manifest(struct ImageMounterHandle *client,
|
||||
const char *image_type,
|
||||
const uint8_t *signature,
|
||||
size_t signature_len,
|
||||
uint8_t **manifest,
|
||||
size_t *manifest_len);
|
||||
|
||||
/**
|
||||
* Queries the nonce from the device
|
||||
*
|
||||
* # Arguments
|
||||
* * [`client`] - A valid ImageMounter handle
|
||||
* * [`personalized_image_type`] - The type of image to query (optional)
|
||||
* * [`nonce`] - Will be set to point to the nonce data on success
|
||||
* * [`nonce_len`] - Will be set to the length of the nonce data
|
||||
*
|
||||
* # Returns
|
||||
* An error code indicating success or failure
|
||||
*
|
||||
* # Safety
|
||||
* `client`, `nonce`, and `nonce_len` must be valid pointers
|
||||
* `personalized_image_type` can be NULL
|
||||
*/
|
||||
enum IdeviceErrorCode image_mounter_query_nonce(struct ImageMounterHandle *client,
|
||||
const char *personalized_image_type,
|
||||
uint8_t **nonce,
|
||||
size_t *nonce_len);
|
||||
|
||||
/**
|
||||
* Queries personalization identifiers from the device
|
||||
*
|
||||
* # Arguments
|
||||
* * [`client`] - A valid ImageMounter handle
|
||||
* * [`image_type`] - The type of image to query (optional)
|
||||
* * [`identifiers`] - Will be set to point to the identifiers plist on success
|
||||
*
|
||||
* # Returns
|
||||
* An error code indicating success or failure
|
||||
*
|
||||
* # Safety
|
||||
* `client` and `identifiers` must be valid pointers
|
||||
* `image_type` can be NULL
|
||||
*/
|
||||
enum IdeviceErrorCode image_mounter_query_personalization_identifiers(struct ImageMounterHandle *client,
|
||||
const char *image_type,
|
||||
void **identifiers);
|
||||
|
||||
/**
|
||||
* Rolls the personalization nonce
|
||||
*
|
||||
* # Arguments
|
||||
* * [`client`] - A valid ImageMounter handle
|
||||
*
|
||||
* # Returns
|
||||
* An error code indicating success or failure
|
||||
*
|
||||
* # Safety
|
||||
* `client` must be a valid pointer to a handle allocated by this library
|
||||
*/
|
||||
enum IdeviceErrorCode image_mounter_roll_personalization_nonce(struct ImageMounterHandle *client);
|
||||
|
||||
/**
|
||||
* Rolls the cryptex nonce
|
||||
*
|
||||
* # Arguments
|
||||
* * [`client`] - A valid ImageMounter handle
|
||||
*
|
||||
* # Returns
|
||||
* An error code indicating success or failure
|
||||
*
|
||||
* # Safety
|
||||
* `client` must be a valid pointer to a handle allocated by this library
|
||||
*/
|
||||
enum IdeviceErrorCode image_mounter_roll_cryptex_nonce(struct ImageMounterHandle *client);
|
||||
|
||||
/**
|
||||
* Mounts a personalized developer image
|
||||
*
|
||||
* # Arguments
|
||||
* * [`client`] - A valid ImageMounter handle
|
||||
* * [`provider`] - A valid provider handle
|
||||
* * [`image`] - Pointer to the image data
|
||||
* * [`image_len`] - Length of the image data
|
||||
* * [`trust_cache`] - Pointer to the trust cache data
|
||||
* * [`trust_cache_len`] - Length of the trust cache data
|
||||
* * [`build_manifest`] - Pointer to the build manifest data
|
||||
* * [`build_manifest_len`] - Length of the build manifest data
|
||||
* * [`info_plist`] - Pointer to info plist (optional)
|
||||
* * [`unique_chip_id`] - The device's unique chip ID
|
||||
*
|
||||
* # Returns
|
||||
* An error code indicating success or failure
|
||||
*
|
||||
* # Safety
|
||||
* All pointers must be valid (except optional ones which can be null)
|
||||
*/
|
||||
enum IdeviceErrorCode image_mounter_mount_personalized_usbmuxd(struct ImageMounterHandle *client,
|
||||
struct UsbmuxdProviderHandle *provider,
|
||||
const uint8_t *image,
|
||||
size_t image_len,
|
||||
const uint8_t *trust_cache,
|
||||
size_t trust_cache_len,
|
||||
const uint8_t *build_manifest,
|
||||
size_t build_manifest_len,
|
||||
const void *info_plist,
|
||||
uint64_t unique_chip_id);
|
||||
|
||||
/**
|
||||
* Mounts a personalized developer image
|
||||
*
|
||||
* # Arguments
|
||||
* * [`client`] - A valid ImageMounter handle
|
||||
* * [`provider`] - A valid provider handle
|
||||
* * [`image`] - Pointer to the image data
|
||||
* * [`image_len`] - Length of the image data
|
||||
* * [`trust_cache`] - Pointer to the trust cache data
|
||||
* * [`trust_cache_len`] - Length of the trust cache data
|
||||
* * [`build_manifest`] - Pointer to the build manifest data
|
||||
* * [`build_manifest_len`] - Length of the build manifest data
|
||||
* * [`info_plist`] - Pointer to info plist (optional)
|
||||
* * [`unique_chip_id`] - The device's unique chip ID
|
||||
*
|
||||
* # Returns
|
||||
* An error code indicating success or failure
|
||||
*
|
||||
* # Safety
|
||||
* All pointers must be valid (except optional ones which can be null)
|
||||
*/
|
||||
enum IdeviceErrorCode image_mounter_mount_personalized_tcp(struct ImageMounterHandle *client,
|
||||
struct TcpProviderHandle *provider,
|
||||
const uint8_t *image,
|
||||
size_t image_len,
|
||||
const uint8_t *trust_cache,
|
||||
size_t trust_cache_len,
|
||||
const uint8_t *build_manifest,
|
||||
size_t build_manifest_len,
|
||||
const void *info_plist,
|
||||
uint64_t unique_chip_id);
|
||||
|
||||
/**
|
||||
* Mounts a personalized developer image with progress callback
|
||||
*
|
||||
* # Arguments
|
||||
* * [`client`] - A valid ImageMounter handle
|
||||
* * [`provider`] - A valid provider handle
|
||||
* * [`image`] - Pointer to the image data
|
||||
* * [`image_len`] - Length of the image data
|
||||
* * [`trust_cache`] - Pointer to the trust cache data
|
||||
* * [`trust_cache_len`] - Length of the trust cache data
|
||||
* * [`build_manifest`] - Pointer to the build manifest data
|
||||
* * [`build_manifest_len`] - Length of the build manifest data
|
||||
* * [`info_plist`] - Pointer to info plist (optional)
|
||||
* * [`unique_chip_id`] - The device's unique chip ID
|
||||
* * [`callback`] - Progress callback function
|
||||
* * [`context`] - User context to pass to callback
|
||||
*
|
||||
* # Returns
|
||||
* An error code indicating success or failure
|
||||
*
|
||||
* # Safety
|
||||
* All pointers must be valid (except optional ones which can be null)
|
||||
*/
|
||||
enum IdeviceErrorCode image_mounter_mount_personalized_usbmuxd_with_callback(struct ImageMounterHandle *client,
|
||||
struct UsbmuxdProviderHandle *provider,
|
||||
const uint8_t *image,
|
||||
size_t image_len,
|
||||
const uint8_t *trust_cache,
|
||||
size_t trust_cache_len,
|
||||
const uint8_t *build_manifest,
|
||||
size_t build_manifest_len,
|
||||
const void *info_plist,
|
||||
uint64_t unique_chip_id,
|
||||
void (*callback)(size_t progress,
|
||||
size_t total,
|
||||
void *context),
|
||||
void *context);
|
||||
|
||||
/**
|
||||
* Mounts a personalized developer image with progress callback
|
||||
*
|
||||
* # Arguments
|
||||
* * [`client`] - A valid ImageMounter handle
|
||||
* * [`provider`] - A valid provider handle
|
||||
* * [`image`] - Pointer to the image data
|
||||
* * [`image_len`] - Length of the image data
|
||||
* * [`trust_cache`] - Pointer to the trust cache data
|
||||
* * [`trust_cache_len`] - Length of the trust cache data
|
||||
* * [`build_manifest`] - Pointer to the build manifest data
|
||||
* * [`build_manifest_len`] - Length of the build manifest data
|
||||
* * [`info_plist`] - Pointer to info plist (optional)
|
||||
* * [`unique_chip_id`] - The device's unique chip ID
|
||||
* * [`callback`] - Progress callback function
|
||||
* * [`context`] - User context to pass to callback
|
||||
*
|
||||
* # Returns
|
||||
* An error code indicating success or failure
|
||||
*
|
||||
* # Safety
|
||||
* All pointers must be valid (except optional ones which can be null)
|
||||
*/
|
||||
enum IdeviceErrorCode image_mounter_mount_personalized_tcp_with_callback(struct ImageMounterHandle *client,
|
||||
struct TcpProviderHandle *provider,
|
||||
const uint8_t *image,
|
||||
size_t image_len,
|
||||
const uint8_t *trust_cache,
|
||||
size_t trust_cache_len,
|
||||
const uint8_t *build_manifest,
|
||||
size_t build_manifest_len,
|
||||
const void *info_plist,
|
||||
uint64_t unique_chip_id,
|
||||
void (*callback)(size_t progress,
|
||||
size_t total,
|
||||
void *context),
|
||||
void *context);
|
||||
|
||||
/**
|
||||
* Reads a pairing file from the specified path
|
||||
*
|
||||
|
|
@ -1633,4 +2009,4 @@ enum IdeviceErrorCode idevice_usbmuxd_unix_addr_new(const char *addr,
|
|||
*/
|
||||
void idevice_usbmuxd_addr_free(struct UsbmuxdAddrHandle *usbmuxd_addr);
|
||||
|
||||
#endif /* IDEVICE_H */
|
||||
#endif
|
||||
|
|
|
|||
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue