use std::borrow::Cow; use clap::Parser; #[derive(Parser, Debug)] #[clap(author, version, about, long_about = None)] struct Args { #[clap(short, long)] hostname: Option, //example: "IServSAT=mvuvFvCZSlpvuwhk0mmNwF1NKEQypM4d; IServSession=xEPqyJO1a5nsVd34HEpbPqQGMMQKapvw; nav-show-additional-modules=true; PHPSESSID=mchbrl11epjnnp851q0i4rt8rc" #[clap(short, long)] session_cookie: Option, #[clap(long)] target_ip: Option, #[clap(long)] target_room: Option, #[clap(long)] target_compilation: Option, } macro_rules! print_banner { ($f: expr, $($arg: expr),*) => { println!(concat!("----------------------------------------\n", $f, "\n----------------------------------------"), $($arg),*) }; } fn main() -> Result<(), Box> { let args = Args::parse(); loop { ipad(&args)?; } } fn ipad(args: &Args) -> Result<(), Box> { let params = [ ("filter[controllable]", ""), ("filter[room][]", "__none"), ("filter[group]", ""), ("filter[search]", "iPad"), ]; let header = ("Cookie", &args.session_cookie); let client = reqwest::blocking::Client::new(); let resp = client .get(format!("https://{}/iserv/admin/hosts", args.hostname.unwrap())) .header(header.0, header.1) .query(¶ms) .send()?; let status = &resp.status(); let plain = &resp.text()?; let content = squeeze( &plain, "", ); let json: serde_json::Value = serde_json::from_str(content).expect("Bad Jason!"); let json_part = &json["data"][0]["name"]["rendered"] .to_string() .replace("\\", ""); // skip rest of loop when no entry appeared if json_part == "null" { println!( "######################################## No new host: skipping (Retry in 5s) ######################################## "); //sleep for 5 seconds std::thread::sleep(std::time::Duration::from_secs(5)); return Ok(()); } let host_id = squeeze(json_part, "data-host-id=\"", "\""); let device_name = squeeze(json_part, "", ""); print_banner!("1/8 Found host\nHost id: {}\nDevice name: {}\nReceived response status: {:?}", host_id, device_name, status); let dest = format!("https://{}/iserv/admin/host/edit/{}", args.hostname, &host_id); let resp = client.get(&dest).header(header.0, header.1).send()?; //TODO Check for non 200 response let status = &resp.status(); if !status.is_success() && *status != 300 { eprintln!("WARN: Found invalid Status Code: {status}"); return Ok(()) } let plain = &resp.text()?; let mut form_ip: &str = &args.target_ip; let form_name = squeeze_html_form(plain, "name=\"host[name]\"", "value=\"", "\""); let form_tags = squeeze_html_form(plain, "name=\"host[tags][]\"", "value=\"", "\""); let form_mac = squeeze_html_form(plain, "name=\"host[mac]\"", "value=\"", "\""); let form_description = squeeze_html_form(plain, "name=\"host[description]\"", ">", "<"); let form_token = squeeze_html_form(plain, "name=\"host[_token]\"", "value=\"", "\""); let mut form_data = [ ("host[name]", form_name), ("host[tags][]", form_tags), ("host[room]", &args.target_room.to_string()), ("host[ip]", &form_ip), ("host[mac]", form_mac), ("host[internet]", "1"), ("host[proxyEnforce]", "0"), ("host[owner]", ""), ("host[controllable]", "0"), ("host[inventoryNumber]", ""), ("host[shutdown]", ""), ("host[description]", form_description), ("host[image][id]", ""), ("host[image][x]", ""), ("host[image][y]", ""), ("host[actions][submit]", ""), ("host[_token]", form_token), ]; print_banner!("2/8 Received current host properties\nReceived response status: {:?}", status); let resp = client .post(&dest) .header(header.0, header.1) .form(&form_data) .send()?; let status = &resp.status(); let plain = &resp.text()?; form_ip = squeeze_html_form(plain, "name=\"host[ip]\"", "value=\"", "\""); form_data[3] = ("host[ip]", form_ip); print_banner!("3/8 Received recommended ip: {}\nReceived response status: {:?}", form_ip, status); let resp = client .post(&dest) .header(header.0, header.1) .form(&form_data) .send()?; let status = &resp.status(); print_banner!("4/8 Sucessfully updated host\nReceived response status: {:?}", status); if args.target_compilation.is_none() { return Ok(()) } let resp = client .get(format!("https://{}/iserv/admin/mdm/ios/compilation/edit/{}", args.hostname, args.target_compilation.unwrap())) .header(header.0, header.1) .send()?; //TODO Check for non 200 response let status = &resp.status(); let plain = &resp.text()?; print_banner!("5/8 Received MDM compilation\nReceived response status: {:?}", status); let mut form_data = Vec::from([ ( "ioscompilation[name]", squeeze_html_form(plain, "name=\"ioscompilation[name]\"", "value=\"", "\"") ), ( "ioscompilation[description]", squeeze_html_form(plain, "name=\"ioscompilation[description]\"", "value=\"", "\"") ), ].map(|(a, b)| (Cow::Borrowed(a), Cow::Borrowed(b)))); // push apps (