mirror of
https://github.com/nab138/isideload.git
synced 2026-03-02 06:26:16 +01:00
start implementing cert identity
This commit is contained in:
103
Cargo.lock
generated
103
Cargo.lock
generated
@@ -118,6 +118,12 @@ version = "0.22.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||
|
||||
[[package]]
|
||||
name = "base64ct"
|
||||
version = "1.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.10.0"
|
||||
@@ -397,6 +403,30 @@ dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "der"
|
||||
version = "0.8.0-rc.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02c1d73e9668ea6b6a28172aa55f3ebec38507131ce179051c8033b5c6037653"
|
||||
dependencies = [
|
||||
"const-oid",
|
||||
"der_derive",
|
||||
"flagset",
|
||||
"pem-rfc7468",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "der_derive"
|
||||
version = "0.8.0-rc.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be645fee2afe89d293b96c19e4456e6ac69520fc9c6b8a58298550138e361ffe"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.5.5"
|
||||
@@ -466,6 +496,12 @@ version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
||||
|
||||
[[package]]
|
||||
name = "flagset"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7ac824320a75a52197e8f2d787f6a38b6718bb6897a35142d749af3c0e8f4fe"
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.1.9"
|
||||
@@ -1004,6 +1040,7 @@ dependencies = [
|
||||
"rootcause",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha1 0.11.0-rc.5",
|
||||
"sha2",
|
||||
"srp",
|
||||
"thiserror 2.0.18",
|
||||
@@ -1011,6 +1048,7 @@ dependencies = [
|
||||
"tokio-tungstenite",
|
||||
"tracing",
|
||||
"uuid",
|
||||
"x509-cert",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1224,6 +1262,15 @@ dependencies = [
|
||||
"hmac",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pem-rfc7468"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a6305423e0e7738146434843d1694d621cce767262b2a86910beab705e4493d9"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "2.3.2"
|
||||
@@ -1723,6 +1770,17 @@ dependencies = [
|
||||
"digest 0.10.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha1"
|
||||
version = "0.11.0-rc.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b167252f3c126be0d8926639c4c4706950f01445900c4b3db0fd7e89fcb750a"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest 0.11.0-rc.11",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.11.0-rc.5"
|
||||
@@ -1777,6 +1835,16 @@ dependencies = [
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spki"
|
||||
version = "0.8.0-rc.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8baeff88f34ed0691978ec34440140e1572b68c7dd4a495fd14a3dc1944daa80"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"der",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "srp"
|
||||
version = "0.7.0-rc.1"
|
||||
@@ -1958,6 +2026,27 @@ version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "tls_codec"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0de2e01245e2bb89d6f05801c564fa27624dbd7b1846859876c7dad82e90bf6b"
|
||||
dependencies = [
|
||||
"tls_codec_derive",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tls_codec_derive"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d2e76690929402faae40aebdda620a2c0e25dd6d3b9afe48867dfd95991f4bd"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.49.0"
|
||||
@@ -2156,7 +2245,7 @@ dependencies = [
|
||||
"rand",
|
||||
"rustls",
|
||||
"rustls-pki-types",
|
||||
"sha1",
|
||||
"sha1 0.10.6",
|
||||
"thiserror 2.0.18",
|
||||
"utf-8",
|
||||
]
|
||||
@@ -2794,6 +2883,18 @@ version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9"
|
||||
|
||||
[[package]]
|
||||
name = "x509-cert"
|
||||
version = "0.3.0-rc.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e21aad3a769f25f3d2d0cbf30ea8b50a1d602354bd6ab687fad112821608ba6"
|
||||
dependencies = [
|
||||
"const-oid",
|
||||
"der",
|
||||
"spki",
|
||||
"tls_codec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yoke"
|
||||
version = "0.8.1"
|
||||
|
||||
@@ -49,7 +49,7 @@ async fn main() {
|
||||
|
||||
let mut account = account.unwrap();
|
||||
|
||||
let mut dev_session = DeveloperSession::from_account(&mut account)
|
||||
let dev_session = DeveloperSession::from_account(&mut account)
|
||||
.await
|
||||
.expect("Failed to create developer session");
|
||||
|
||||
@@ -70,26 +70,28 @@ async fn main() {
|
||||
.unwrap()
|
||||
.to_provider(UsbmuxdAddr::from_env_var().unwrap(), "isideload-demo");
|
||||
|
||||
let builder = SideloaderBuilder::new().team_selection(TeamSelection::Prompt(|teams| {
|
||||
println!("Please select a team:");
|
||||
for (index, team) in teams.iter().enumerate() {
|
||||
println!(
|
||||
"{}: {} ({})",
|
||||
index + 1,
|
||||
team.name.as_deref().unwrap_or("<Unnamed>"),
|
||||
team.team_id
|
||||
);
|
||||
}
|
||||
let mut input = String::new();
|
||||
std::io::stdin().read_line(&mut input).unwrap();
|
||||
let selection = input.trim().parse::<usize>().ok()?;
|
||||
if selection == 0 || selection > teams.len() {
|
||||
return None;
|
||||
}
|
||||
Some(teams[selection - 1].team_id.clone())
|
||||
}));
|
||||
let mut sideloader = SideloaderBuilder::new(dev_session)
|
||||
.team_selection(TeamSelection::Prompt(|teams| {
|
||||
println!("Please select a team:");
|
||||
for (index, team) in teams.iter().enumerate() {
|
||||
println!(
|
||||
"{}: {} ({})",
|
||||
index + 1,
|
||||
team.name.as_deref().unwrap_or("<Unnamed>"),
|
||||
team.team_id
|
||||
);
|
||||
}
|
||||
let mut input = String::new();
|
||||
std::io::stdin().read_line(&mut input).unwrap();
|
||||
let selection = input.trim().parse::<usize>().ok()?;
|
||||
if selection == 0 || selection > teams.len() {
|
||||
return None;
|
||||
}
|
||||
Some(teams[selection - 1].team_id.clone())
|
||||
}))
|
||||
.build();
|
||||
|
||||
// let result = bu(&provider, &mut dev_session, app_path, &sideload_config).await;
|
||||
let result = sideloader.install_app(&provider, app_path).await;
|
||||
match result {
|
||||
Ok(_) => println!("App installed successfully"),
|
||||
Err(e) => panic!("Failed to install app: {:?}", e),
|
||||
|
||||
@@ -25,7 +25,6 @@ async-trait = "0.1.89"
|
||||
serde = "1.0.228"
|
||||
rand = "0.9.2"
|
||||
uuid = {version = "1.20.0", features = ["v4"] }
|
||||
sha2 = "0.11.0-rc.5"
|
||||
tracing = "0.1.44"
|
||||
tokio-tungstenite = { version = "0.28.0", features = ["rustls-tls-webpki-roots"] }
|
||||
rootcause = "0.11.1"
|
||||
@@ -33,6 +32,8 @@ futures-util = "0.3.31"
|
||||
serde_json = "1.0.149"
|
||||
base64 = "0.22.1"
|
||||
hex = "0.4.3"
|
||||
sha1 = "0.11.0-rc.5"
|
||||
sha2 = "0.11.0-rc.5"
|
||||
srp = "0.7.0-rc.1"
|
||||
pbkdf2 = "0.13.0-rc.9"
|
||||
hmac = "0.13.0-rc.5"
|
||||
@@ -41,3 +42,4 @@ aes = "0.9.0-rc.4"
|
||||
aes-gcm = "0.11.0-rc.3"
|
||||
tokio = "1.49.0"
|
||||
keyring = { version = "3.6.3", features = ["apple-native", "linux-native-sync-persistent", "windows-native"], optional = true }
|
||||
x509-cert = "0.3.0-rc.4"
|
||||
|
||||
@@ -97,6 +97,33 @@ pub trait CertificatesApi {
|
||||
Ok(certs)
|
||||
}
|
||||
|
||||
async fn list_ios_certs(
|
||||
&mut self,
|
||||
team: &DeveloperTeam,
|
||||
) -> Result<Vec<DevelopmentCertificate>, Report> {
|
||||
let certs = self
|
||||
.list_all_development_certs(team, DeveloperDeviceType::Ios)
|
||||
.await?;
|
||||
|
||||
Ok(certs
|
||||
.into_iter()
|
||||
.filter(|c| {
|
||||
if let Some(platform) = &c.certificate_platform {
|
||||
platform.to_lowercase() == "ios"
|
||||
} else if let Some(cert_type) = &c.certificate_type {
|
||||
if let Some(platform) = &cert_type.platform {
|
||||
platform.to_lowercase() == "ios"
|
||||
} else {
|
||||
// I don't know how consistently these field is populated because apple apis are stupid, and I don't want to break things so just assume
|
||||
true
|
||||
}
|
||||
} else {
|
||||
true
|
||||
}
|
||||
})
|
||||
.collect())
|
||||
}
|
||||
|
||||
async fn revoke_development_cert(
|
||||
&mut self,
|
||||
team: &DeveloperTeam,
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
use std::fmt::Display;
|
||||
|
||||
use crate::{dev::teams::DeveloperTeam, util::storage::SideloadingStorage};
|
||||
use crate::{
|
||||
dev::{developer_session::DeveloperSession, teams::DeveloperTeam},
|
||||
sideload::sideloader::Sideloader,
|
||||
util::storage::SideloadingStorage,
|
||||
};
|
||||
|
||||
/// Configuration for selecting a developer team during sideloading
|
||||
///
|
||||
@@ -23,22 +27,18 @@ impl Display for TeamSelection {
|
||||
}
|
||||
|
||||
pub struct SideloaderBuilder {
|
||||
pub team_selection: TeamSelection,
|
||||
pub storage: Box<dyn SideloadingStorage>,
|
||||
}
|
||||
|
||||
impl Default for SideloaderBuilder {
|
||||
fn default() -> Self {
|
||||
SideloaderBuilder {
|
||||
team_selection: TeamSelection::First,
|
||||
storage: Box::new(crate::util::storage::new_storage()),
|
||||
}
|
||||
}
|
||||
team_selection: TeamSelection,
|
||||
storage: Box<dyn SideloadingStorage>,
|
||||
developer_session: DeveloperSession,
|
||||
}
|
||||
|
||||
impl SideloaderBuilder {
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
pub fn new(developer_session: DeveloperSession) -> Self {
|
||||
SideloaderBuilder {
|
||||
team_selection: TeamSelection::First,
|
||||
storage: Box::new(crate::util::storage::new_storage()),
|
||||
developer_session,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn team_selection(mut self, selection: TeamSelection) -> Self {
|
||||
@@ -50,4 +50,8 @@ impl SideloaderBuilder {
|
||||
self.storage = storage;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> Sideloader {
|
||||
Sideloader::new(self.team_selection, self.storage, self.developer_session)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,63 @@
|
||||
use rootcause::prelude::*;
|
||||
use tracing::{error, info};
|
||||
|
||||
use crate::{
|
||||
dev::{
|
||||
certificates::CertificatesApi, developer_session::DeveloperSession, teams::DeveloperTeam,
|
||||
},
|
||||
util::storage::SideloadingStorage,
|
||||
};
|
||||
|
||||
pub struct CertificateIdentity {
|
||||
pub machine_id: String,
|
||||
pub machine_name: String,
|
||||
}
|
||||
|
||||
impl CertificateIdentity {}
|
||||
impl CertificateIdentity {
|
||||
pub async fn retrieve(
|
||||
machine_name: &str,
|
||||
developer_session: DeveloperSession,
|
||||
team: &DeveloperTeam,
|
||||
storage: &dyn SideloadingStorage,
|
||||
) -> Result<Self, Report> {
|
||||
let stored =
|
||||
Self::retrieve_from_storage(machine_name, developer_session, team, storage).await;
|
||||
if let Ok(Some(cert)) = stored {
|
||||
return Ok(cert);
|
||||
}
|
||||
|
||||
if let Err(e) = stored {
|
||||
error!("Failed to load certificate from storage: {:?}", e);
|
||||
} else {
|
||||
info!("No stored certificate found, generating");
|
||||
}
|
||||
|
||||
todo!("generate CSR")
|
||||
}
|
||||
|
||||
async fn retrieve_from_storage(
|
||||
machine_name: &str,
|
||||
developer_session: DeveloperSession,
|
||||
team: &DeveloperTeam,
|
||||
storage: &dyn SideloadingStorage,
|
||||
) -> Result<Option<Self>, Report> {
|
||||
let cert = storage.retrieve_data("cert")?;
|
||||
if cert.is_none() {
|
||||
return Ok(None);
|
||||
}
|
||||
let cert = cert.unwrap();
|
||||
let private_key = storage.retrieve_data("key")?;
|
||||
if private_key.is_none() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
for cert in developer_session
|
||||
.list_ios_certs(team)
|
||||
.await?
|
||||
.iter()
|
||||
.filter(|c| c.machine_name.unwrap_or_default() == machine_name)
|
||||
{}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,12 +15,24 @@ use rootcause::prelude::*;
|
||||
use tracing::info;
|
||||
|
||||
pub struct Sideloader {
|
||||
pub team_selection: TeamSelection,
|
||||
pub storage: Box<dyn SideloadingStorage>,
|
||||
pub dev_session: DeveloperSession,
|
||||
team_selection: TeamSelection,
|
||||
storage: Box<dyn SideloadingStorage>,
|
||||
dev_session: DeveloperSession,
|
||||
}
|
||||
|
||||
impl Sideloader {
|
||||
pub fn new(
|
||||
team_selection: TeamSelection,
|
||||
storage: Box<dyn SideloadingStorage>,
|
||||
dev_session: DeveloperSession,
|
||||
) -> Self {
|
||||
Sideloader {
|
||||
team_selection,
|
||||
storage,
|
||||
dev_session,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn install_app(
|
||||
&mut self,
|
||||
device_provider: &impl IdeviceProvider,
|
||||
|
||||
Reference in New Issue
Block a user