Files
anisette-js/example/anisette.rs
2026-02-26 17:04:29 +08:00

90 lines
3.0 KiB
Rust

use std::fs;
use std::path::{Path, PathBuf};
use anisette_rs::{Adi, AdiInit, Device, ProvisioningSession, init_idbfs_for_path, sync_idbfs};
use anyhow::{Context, Result};
use base64::{Engine as _, engine::general_purpose::STANDARD};
use serde_json::json;
fn main() -> Result<()> {
// Usage:
// cargo run --example anisette -- <libstoreservicescore.so> <libCoreADI.so> <library_path> [dsid] [apple_root_pem]
let storeservices_path = std::env::args()
.nth(1)
.unwrap_or_else(|| "libstoreservicescore.so".to_string());
let coreadi_path = std::env::args()
.nth(2)
.unwrap_or_else(|| "libCoreADI.so".to_string());
let library_path = std::env::args()
.nth(3)
.unwrap_or_else(|| "./anisette/".to_string());
let dsid_raw = std::env::args().nth(4).unwrap_or_else(|| "-2".to_string());
let apple_root_pem = std::env::args().nth(5).map(PathBuf::from);
let _mount_path = init_idbfs_for_path(&library_path)
.map_err(|e| anyhow::anyhow!("failed to initialize IDBFS: {e}"))?;
fs::create_dir_all(&library_path)
.with_context(|| format!("failed to create library path: {library_path}"))?;
let device_path = Path::new(&library_path).join("device.json");
let mut device = Device::load(&device_path)?;
let storeservicescore = fs::read(&storeservices_path)
.with_context(|| format!("failed to read {storeservices_path}"))?;
let coreadi =
fs::read(&coreadi_path).with_context(|| format!("failed to read {coreadi_path}"))?;
let mut adi = Adi::new(AdiInit {
storeservicescore,
coreadi,
library_path: library_path.clone(),
provisioning_path: Some(library_path.clone()),
identifier: None,
})?;
if !device.initialized {
println!("Initializing device");
device.initialize_defaults();
device.persist()?;
} else {
println!(
"(Device initialized: server-description='{}' device-uid='{}' adi='{}' user-uid='{}')",
device.data.server_friendly_description,
device.data.unique_device_identifier,
device.data.adi_identifier,
device.data.local_user_uuid
);
}
adi.set_identifier(&device.data.adi_identifier)?;
let dsid = if let Some(hex) = dsid_raw.strip_prefix("0x") {
u64::from_str_radix(hex, 16)?
} else {
let signed: i64 = dsid_raw.parse()?;
signed as u64
};
let is_provisioned = adi.is_machine_provisioned(dsid)?;
if !is_provisioned {
println!("Provisioning...");
let mut provisioning_session =
ProvisioningSession::new(&mut adi, &device.data, apple_root_pem)?;
provisioning_session.provision(dsid)?;
} else {
println!("(Already provisioned)");
}
let otp = adi.request_otp(dsid)?;
let headers = json!({
"X-Apple-I-MD": STANDARD.encode(otp.otp),
"X-Apple-I-MD-M": STANDARD.encode(otp.machine_id),
});
let _ = sync_idbfs(false);
println!("{}", serde_json::to_string_pretty(&headers)?);
Ok(())
}