Compare commits

..

No commits in common. "master" and "master" have entirely different histories.

1 changed files with 26 additions and 43 deletions

View File

@ -34,11 +34,11 @@ fn ipad(args: &Args) -> Result<(), Box<dyn std::error::Error>> {
("filter[group]", ""), ("filter[group]", ""),
("filter[search]", "iPad"), ("filter[search]", "iPad"),
]; ];
let header = ("Cookie", &args.session_cookie); let header = ("Cookie", args.session_cookie.to_owned());
let client = reqwest::blocking::Client::new(); let client = reqwest::blocking::Client::new();
let resp = client let resp = client
.get(format!("https://{}/iserv/admin/hosts", args.hostname)) .get(format!("https://{}/iserv/admin/hosts", args.hostname))
.header(header.0, header.1) .header(header.0, header.to_owned().1)
.query(&params) .query(&params)
.send()?; .send()?;
let status = &resp.status(); let status = &resp.status();
@ -65,10 +65,10 @@ No new host: skipping (Retry in 5s)
} }
let host_id = squeeze(json_part, "data-host-id=\"", "\""); let host_id = squeeze(json_part, "data-host-id=\"", "\"");
let device_name = squeeze(json_part, "</span>", "</a>"); let device_name = squeeze(json_part, "</span>", "</a>");
print_banner!("1/8 Found host\nHost id: {}\nDevice name: {}\nReceived response status: {:?}", host_id, device_name, status); print_banner!("1/7 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 dest = format!("https://{}/iserv/admin/host/edit/{}", args.hostname, &host_id);
let resp = client.get(&dest).header(header.0, header.1).send()?; let resp = client.get(&dest).header(header.0, header.to_owned().1).send()?;
//TODO Check for non 200 response //TODO Check for non 200 response
let status = &resp.status(); let status = &resp.status();
if !status.is_success() && *status != 300 { if !status.is_success() && *status != 300 {
@ -101,40 +101,38 @@ No new host: skipping (Retry in 5s)
("host[actions][submit]", ""), ("host[actions][submit]", ""),
("host[_token]", form_token), ("host[_token]", form_token),
]; ];
print_banner!("2/8 Received current host properties\nReceived response status: {:?}", status); print_banner!("2/7 Received current host properties\nReceived response status: {:?}", status);
let resp = client let resp = client
.post(&dest) .post(&dest)
.header(header.0, header.1) .header(header.0, header.to_owned().1)
.form(&form_data) .form(&form_data)
.send()?; .send()?;
let status = &resp.status(); let status = &resp.status();
let plain = &resp.text()?; let plain = &resp.text()?;
form_ip = squeeze_html_form(plain, "name=\"host[ip]\"", "value=\"", "\""); form_ip = squeeze_html_form(plain, "name=\"host[ip]\"", "value=\"", "\"");
form_data[3] = ("host[ip]", form_ip); form_data[3] = ("host[ip]", form_ip);
print_banner!("3/8 Received recommended ip: {}\nReceived response status: {:?}", form_ip, status); print_banner!("3/7 Received recommended ip: {}\nReceived response status: {:?}", form_ip, status);
let resp = client let resp = client
.post(&dest) .post(&dest)
.header(header.0, header.1) .header(header.0, header.to_owned().1)
.form(&form_data) .form(&form_data)
.send()?; .send()?;
let status = &resp.status(); let status = &resp.status();
print_banner!("4/8 Sucessfully updated host\nReceived response status: {:?}", status); print_banner!("4/7 Sucessfully updated host\nReceived response status: {:?}", status);
if args.target_compilation.is_none() { return Ok(()) } if args.target_compilation.is_none() { return Ok(()) }
let resp = client let resp = client
.get(format!("https://{}/iserv/admin/mdm/ios/compilation/edit/{}", args.hostname, args.target_compilation.unwrap())) .get(format!("https://{}/iserv/admin/mdm/ios/compilation/edit/{}", args.hostname, args.target_compilation.unwrap()))
.header(header.0, header.1) .header(header.0, header.to_owned().1)
.send()?; .send()?;
//TODO Check for non 200 response //TODO Check for non 200 response
let status = &resp.status(); let status = &resp.status();
let plain = &resp.text()?; let plain = &resp.text()?;
print_banner!("5/8 Received MDM compilation\nReceived response status: {:?}", status); print_banner!("5/7 Received MDM compilation\nReceived response status: {:?}", status);
//let csrf_token = squeeze_html_form(plain, "name=\"ioscompilation[_token]\"", "value=\"", "\"");
let mut form_data = Vec::from([ let mut form_data = Vec::from([
( (
"ioscompilation[name]", "ioscompilation[name]",
@ -149,15 +147,12 @@ No new host: skipping (Retry in 5s)
// push apps (<option value="52" selected="selected">) // push apps (<option value="52" selected="selected">)
let plain_inner_applications = squeeze_html_form(plain, "name=\"ioscompilation[applications][]\"", ">", "</select>"); let plain_inner_applications = squeeze_html_form(plain, "name=\"ioscompilation[applications][]\"", ">", "</select>");
squeeze_loop(&mut form_data, plain_inner_applications, "<option value=\"", "\"", " selected=\"selected\"", 3, "ioscompilation[applications][]"); squeeze_loop(&mut form_data, plain_inner_applications, "<option value=\"", "\"", " selected=\"selected\"", 3, "ioscompilation[applications][]");
// push profiles // push profiles
let plain_inner_profiles = squeeze_html_form(plain, "name=\"ioscompilation[profiles][]\"", ">", "</select>"); let plain_inner_profiles = squeeze_html_form(plain, "name=\"ioscompilation[profiles][]\"", ">", "</select>");
squeeze_loop(&mut form_data, plain_inner_profiles, "<option value=\"", "\"", " selected=\"selected\"", 3, "ioscompilation[profiles][]"); squeeze_loop(&mut form_data, plain_inner_profiles, "<option value=\"", "\"", " selected=\"selected\"", 3, "ioscompilation[profiles][]");
// push existing devices ([\s\n]* seems not needed) // push existing devices ([\s\n]* seems not needed)
let plain_inner_devices = squeeze_html_form(plain, "name=\"ioscompilation[devices][]\"", ">", "</select>"); let plain_inner_devices = squeeze_html_form(plain, "name=\"ioscompilation[devices][]\"", ">", "</select>");
squeeze_loop(&mut form_data, plain_inner_devices, "<option value=\"", "\"", " selected=\"selected\"", 3, "ioscompilation[devices][]"); squeeze_loop(&mut form_data, plain_inner_devices, "<option value=\"", "\"", " selected=\"selected\"", 3, "ioscompilation[devices][]");
// push new device // push new device
let mdm_new_ipad_id = squeeze_right(plain_inner_devices, "<option value=\"", &format!("\">{}", form_name)); let mdm_new_ipad_id = squeeze_right(plain_inner_devices, "<option value=\"", &format!("\">{}", form_name));
if plain_inner_devices.contains(form_name) { if plain_inner_devices.contains(form_name) {
@ -165,49 +160,40 @@ No new host: skipping (Retry in 5s)
} else { } else {
eprintln!("Device not found in compilation edit.") eprintln!("Device not found in compilation edit.")
} }
// push submit action // push submit action
form_data.push(("ioscompilation[actions][submit]".into(), "".into())); form_data.push(("ioscompilation[actions][submit]".into(), "".into()));
//push token //push token
let form_token = squeeze_html_form(plain, "name=\"ioscompilation[_token]\"", "value=\"", "\""); let form_token = squeeze_html_form(plain, "name=\"ioscompilation[_token]\"", "value=\"", "\"");
form_data.push(("ioscompilation[_token]".into(), form_token.into())); form_data.push(("ioscompilation[_token]".into(), form_token.into()));
let resp = client let resp = client
.post(format!("https://{}/iserv/admin/mdm/ios/compilation/edit/{}", args.hostname, args.target_compilation.unwrap())) .post(format!("https://{}/iserv/admin/mdm/ios/compilation/edit/{}", args.hostname, args.target_compilation.unwrap()))
.header(header.0, header.1) .header(header.0, header.to_owned().1)
.form(&form_data) .form(&form_data)
.send()?; .send()?;
let status = &resp.status();
print_banner!("6/8 Added device to MDM Compilation\nReceived response status: {:?}", status);
let resp = client
.get(format!("https://{}/iserv/admin/mdm/ios/device", args.hostname))
.header(header.0, header.1)
.send()?;
let status = &resp.status(); let status = &resp.status();
let plain = &resp.text()?; let plain = &resp.text()?;
let csrf_token = squeeze_html_form(plain, "name=\"iserv_crud_multi_select[_token]\"", "value=\"", "\""); std::fs::write("device-add.out.html", plain).unwrap();
print_banner!("6/7 Added device to MDM Compilation\nReceived response status: {:?}", status);
print_banner!("7/8 Retrieved CSRF token\nReceived response status: {:?}", status);
let form_data = [ let form_data = [
("iserv_crud_multi_select[confirm]", "apply-changes"), ("iserv_crud_multi_select[confirm]", "apply-changes"),
("iserv_crud_multi_select[multi][]", mdm_new_ipad_id), ("iserv_crud_multi_select[multi][]", mdm_new_ipad_id),
("iserv_crud_multi_select[topReplacementActions][apply-changes]", ""), ("iserv_crud_multi_select[topReplacementActions][apply-changes]", ""),
("iserv_crud_multi_select[_token]", csrf_token), //("iserv_crud_multi_select[_token]", csrf_token),
// seems to work with and without token :o (but without it iserv throws a csrf error) // example token: rqB8um_Y6sJ1hCFMeVlg9r3L0v__tH3GS5KcV4Lj_ug
]; ];
let resp = client let resp = client
.post(format!("https://{}/iserv/admin/mdm/ios/device/batch", args.hostname)) .post(format!("https://{}/iserv/admin/mdm/ios/device/batch", args.hostname))
.header(header.0, header.1) .header(header.0, header.to_owned().1)
.form(&form_data) .form(&form_data)
.send()?; .send()?;
let status = &resp.status(); let status = &resp.status();
print_banner!("8/8 Confirmed device actions\nReceived response status: {:?}", status); let plain = &resp.text()?;
std::fs::write("confirm.out.html", plain).unwrap();
print_banner!("7/7 Confirmed device actions\nReceived response status: {:?}", status);
Ok(()) Ok(())
} }
// helper functions (needed for naive html parsing) // helper functions
fn squeeze<'inp>(input: &'inp str, before: &str, after: &str) -> &'inp str { fn squeeze<'inp>(input: &'inp str, before: &str, after: &str) -> &'inp str {
//find before occurence (excluded from output) //find before occurence (excluded from output)
@ -225,7 +211,6 @@ fn squeeze<'inp>(input: &'inp str, before: &str, after: &str) -> &'inp str {
} }
"" ""
} }
fn squeeze_right<'inp>(input: &'inp str, before: &str, after: &str) -> &'inp str { fn squeeze_right<'inp>(input: &'inp str, before: &str, after: &str) -> &'inp str {
//find before occurence (excluded from output) //find before occurence (excluded from output)
if let Some(after_bytes) = input.find (after) { if let Some(after_bytes) = input.find (after) {
@ -241,7 +226,6 @@ fn squeeze_right<'inp>(input: &'inp str, before: &str, after: &str) -> &'inp str
} }
"" ""
} }
fn squeeze_html_form<'inp>( fn squeeze_html_form<'inp>(
input: &'inp str, input: &'inp str,
first: &str, first: &str,
@ -265,7 +249,6 @@ fn squeeze_html_form<'inp>(
} }
"" ""
} }
fn squeeze_loop<'inp>( fn squeeze_loop<'inp>(
collector: &mut Vec<(Cow<'inp, str>, Cow<'inp, str>)>, collector: &mut Vec<(Cow<'inp, str>, Cow<'inp, str>)>,
input: &'inp str, input: &'inp str,
@ -285,7 +268,7 @@ fn squeeze_loop<'inp>(
if let Some(after_bytes) = leftover.find(after) { if let Some(after_bytes) = leftover.find(after) {
let absolute_after_bytes = after_bytes + adjusted_before_bytes; let absolute_after_bytes = after_bytes + adjusted_before_bytes;
leftover = &leftover[after_bytes + after.len()..]; leftover = &leftover[after_bytes + after.len()..];
// ensure bytes are not equal and that the item is "selected"/enabled // ensure bytes are not equal
if let Some(must_include_distance) = leftover.find(must_include_after) { if let Some(must_include_distance) = leftover.find(must_include_after) {
if adjusted_before_bytes < absolute_after_bytes && must_include_distance < include_after_distance { if adjusted_before_bytes < absolute_after_bytes && must_include_distance < include_after_distance {
collector.push((index_name.into(), input[adjusted_before_bytes..absolute_after_bytes].into())); collector.push((index_name.into(), input[adjusted_before_bytes..absolute_after_bytes].into()));