Fix confirm step and refactoring
- Removed superfluous to_owned() - Fixed CSRF token retrieval for confirm step
This commit is contained in:
		
							
								
								
									
										69
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										69
									
								
								src/main.rs
									
									
									
									
									
								
							@@ -34,11 +34,11 @@ fn ipad(args: &Args) -> Result<(), Box<dyn std::error::Error>> {
 | 
			
		||||
        ("filter[group]", ""),
 | 
			
		||||
        ("filter[search]", "iPad"),
 | 
			
		||||
    ];
 | 
			
		||||
    let header = ("Cookie", args.session_cookie.to_owned());
 | 
			
		||||
    let header = ("Cookie", &args.session_cookie);
 | 
			
		||||
    let client = reqwest::blocking::Client::new();
 | 
			
		||||
    let resp = client
 | 
			
		||||
        .get(format!("https://{}/iserv/admin/hosts", args.hostname))
 | 
			
		||||
        .header(header.0, header.to_owned().1)
 | 
			
		||||
        .header(header.0, header.1)
 | 
			
		||||
        .query(¶ms)
 | 
			
		||||
        .send()?;
 | 
			
		||||
    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 device_name = squeeze(json_part, "</span>", "</a>");
 | 
			
		||||
    print_banner!("1/7 Found host\nHost id: {}\nDevice name: {}\nReceived response status: {:?}", host_id, device_name, status);
 | 
			
		||||
    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.to_owned().1).send()?;
 | 
			
		||||
    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 {
 | 
			
		||||
@@ -101,38 +101,40 @@ No new host: skipping (Retry in 5s)
 | 
			
		||||
        ("host[actions][submit]", ""),
 | 
			
		||||
        ("host[_token]", form_token),
 | 
			
		||||
    ];
 | 
			
		||||
    print_banner!("2/7 Received current host properties\nReceived response status: {:?}", status);
 | 
			
		||||
    print_banner!("2/8 Received current host properties\nReceived response status: {:?}", status);
 | 
			
		||||
 | 
			
		||||
    let resp = client
 | 
			
		||||
        .post(&dest)
 | 
			
		||||
        .header(header.0, header.to_owned().1)
 | 
			
		||||
        .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/7 Received recommended ip: {}\nReceived response status: {:?}", form_ip, status);
 | 
			
		||||
    print_banner!("3/8 Received recommended ip: {}\nReceived response status: {:?}", form_ip, status);
 | 
			
		||||
 | 
			
		||||
    let resp = client
 | 
			
		||||
        .post(&dest)
 | 
			
		||||
        .header(header.0, header.to_owned().1)
 | 
			
		||||
        .header(header.0, header.1)
 | 
			
		||||
        .form(&form_data)
 | 
			
		||||
        .send()?;
 | 
			
		||||
    let status = &resp.status();
 | 
			
		||||
    print_banner!("4/7 Sucessfully updated host\nReceived response status: {:?}", 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.to_owned().1)
 | 
			
		||||
    .header(header.0, header.1)
 | 
			
		||||
    .send()?;
 | 
			
		||||
    //TODO Check for non 200 response
 | 
			
		||||
    
 | 
			
		||||
    let status = &resp.status();
 | 
			
		||||
    let plain = &resp.text()?;
 | 
			
		||||
    
 | 
			
		||||
    print_banner!("5/7 Received MDM compilation\nReceived response status: {:?}", status);
 | 
			
		||||
    
 | 
			
		||||
    //let csrf_token = squeeze_html_form(plain, "name=\"ioscompilation[_token]\"", "value=\"", "\"");
 | 
			
		||||
    print_banner!("5/8 Received MDM compilation\nReceived response status: {:?}", status);
 | 
			
		||||
 | 
			
		||||
    let mut form_data = Vec::from([
 | 
			
		||||
        (
 | 
			
		||||
            "ioscompilation[name]",
 | 
			
		||||
@@ -143,16 +145,19 @@ No new host: skipping (Retry in 5s)
 | 
			
		||||
            squeeze_html_form(plain, "name=\"ioscompilation[description]\"", "value=\"", "\"")
 | 
			
		||||
        ),
 | 
			
		||||
    ].map(|(a, b)| (Cow::Borrowed(a), Cow::Borrowed(b))));
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    // push apps (<option value="52" selected="selected">)
 | 
			
		||||
    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][]");
 | 
			
		||||
 | 
			
		||||
    // push profiles
 | 
			
		||||
    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][]");
 | 
			
		||||
 | 
			
		||||
    // push existing devices ([\s\n]* seems not needed)
 | 
			
		||||
    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][]");
 | 
			
		||||
 | 
			
		||||
    // push new device
 | 
			
		||||
    let mdm_new_ipad_id = squeeze_right(plain_inner_devices, "<option value=\"", &format!("\">{}", form_name));
 | 
			
		||||
    if plain_inner_devices.contains(form_name) {
 | 
			
		||||
@@ -160,40 +165,49 @@ No new host: skipping (Retry in 5s)
 | 
			
		||||
    } else {
 | 
			
		||||
        eprintln!("Device not found in compilation edit.")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // push submit action
 | 
			
		||||
    form_data.push(("ioscompilation[actions][submit]".into(), "".into()));
 | 
			
		||||
    //push token
 | 
			
		||||
    let form_token = squeeze_html_form(plain, "name=\"ioscompilation[_token]\"", "value=\"", "\"");
 | 
			
		||||
    form_data.push(("ioscompilation[_token]".into(), form_token.into()));
 | 
			
		||||
    let resp = client
 | 
			
		||||
        .post(format!("https://{}/iserv/admin/mdm/ios/compilation/edit/{}", args.hostname, args.target_compilation.unwrap()))
 | 
			
		||||
        .header(header.0, header.to_owned().1)
 | 
			
		||||
    .post(format!("https://{}/iserv/admin/mdm/ios/compilation/edit/{}", args.hostname, args.target_compilation.unwrap()))
 | 
			
		||||
        .header(header.0, header.1)
 | 
			
		||||
        .form(&form_data)
 | 
			
		||||
        .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 plain = &resp.text()?;
 | 
			
		||||
    std::fs::write("device-add.out.html", plain).unwrap();
 | 
			
		||||
    print_banner!("6/7 Added device to MDM Compilation\nReceived response status: {:?}", status);
 | 
			
		||||
    let csrf_token = squeeze_html_form(plain, "name=\"iserv_crud_multi_select[_token]\"", "value=\"", "\"");
 | 
			
		||||
 | 
			
		||||
    print_banner!("7/8 Retrieved CSRF token\nReceived response status: {:?}", status);
 | 
			
		||||
        
 | 
			
		||||
    let form_data = [
 | 
			
		||||
        ("iserv_crud_multi_select[confirm]", "apply-changes"),
 | 
			
		||||
        ("iserv_crud_multi_select[multi][]", mdm_new_ipad_id),
 | 
			
		||||
        ("iserv_crud_multi_select[topReplacementActions][apply-changes]", ""),
 | 
			
		||||
        //("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
 | 
			
		||||
        ("iserv_crud_multi_select[_token]", csrf_token),
 | 
			
		||||
    ];
 | 
			
		||||
    let resp = client
 | 
			
		||||
        .post(format!("https://{}/iserv/admin/mdm/ios/device/batch", args.hostname))
 | 
			
		||||
        .header(header.0, header.to_owned().1)
 | 
			
		||||
        .header(header.0, header.1)
 | 
			
		||||
        .form(&form_data)
 | 
			
		||||
        .send()?;
 | 
			
		||||
    let status = &resp.status();
 | 
			
		||||
    let plain = &resp.text()?;
 | 
			
		||||
    std::fs::write("confirm.out.html", plain).unwrap();
 | 
			
		||||
    print_banner!("7/7 Confirmed device actions\nReceived response status: {:?}", status);
 | 
			
		||||
    print_banner!("8/8 Confirmed device actions\nReceived response status: {:?}", status);
 | 
			
		||||
    Ok(())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// helper functions
 | 
			
		||||
// helper functions (needed for naive html parsing)
 | 
			
		||||
 | 
			
		||||
fn squeeze<'inp>(input: &'inp str, before: &str, after: &str) -> &'inp str {
 | 
			
		||||
    //find before occurence (excluded from output)
 | 
			
		||||
@@ -211,6 +225,7 @@ 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 {
 | 
			
		||||
    //find before occurence (excluded from output)
 | 
			
		||||
    if let Some(after_bytes) = input.find (after) {
 | 
			
		||||
@@ -226,6 +241,7 @@ fn squeeze_right<'inp>(input: &'inp str, before: &str, after: &str) -> &'inp str
 | 
			
		||||
    }
 | 
			
		||||
    ""
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn squeeze_html_form<'inp>(
 | 
			
		||||
    input: &'inp str,
 | 
			
		||||
    first: &str,
 | 
			
		||||
@@ -249,6 +265,7 @@ fn squeeze_html_form<'inp>(
 | 
			
		||||
    }
 | 
			
		||||
    ""
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn squeeze_loop<'inp>(
 | 
			
		||||
    collector: &mut Vec<(Cow<'inp, str>, Cow<'inp, str>)>,
 | 
			
		||||
    input: &'inp str,
 | 
			
		||||
@@ -268,7 +285,7 @@ fn squeeze_loop<'inp>(
 | 
			
		||||
        if let Some(after_bytes) = leftover.find(after) {
 | 
			
		||||
            let absolute_after_bytes = after_bytes + adjusted_before_bytes;
 | 
			
		||||
            leftover = &leftover[after_bytes + after.len()..];
 | 
			
		||||
            // ensure bytes are not equal
 | 
			
		||||
            // ensure bytes are not equal and that the item is "selected"/enabled
 | 
			
		||||
            if let Some(must_include_distance) = leftover.find(must_include_after) {
 | 
			
		||||
                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()));
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user