diff --git a/docs/_docs/user-guide/eldritch.md b/docs/_docs/user-guide/eldritch.md index 361729a12..2132a69be 100644 --- a/docs/_docs/user-guide/eldritch.md +++ b/docs/_docs/user-guide/eldritch.md @@ -414,21 +414,23 @@ The file.find method finds all files matching the used parameters. Return ## HTTP +The HTTP library also allows the user to allow the http client to ignore TLS validation via the `allow_insecure` optional parameter (defaults to `false`). + ### http.download -`http.download(uri: str, dst: str) -> None` +`http.download(uri: str, dst: str, allow_insecure: Option) -> None` The http.download method downloads a file at the URI specified in `uri` to the path specified in `dst`. If a file already exists at that location, it will be overwritten. ### http.get -`http.get(uri: str, query_params: Option>, headers: Option>) -> str` +`http.get(uri: str, query_params: Option>, headers: Option>, allow_insecure: Option) -> str` The http.get method sends an HTTP GET request to the URI specified in `uri` with the optional query paramters specified in `query_params` and headers specified in `headers`, then return the response body as a string. Note: in order to conform with HTTP2+ all header names are transmuted to lowercase. ### http.post -`http.post(uri: str, body: Option, form: Option>, headers: Option>) -> str` +`http.post(uri: str, body: Option, form: Option>, headers: Option>, allow_insecure: Option) -> str` The http.post method sends an HTTP POST request to the URI specified in `uri` with the optional request body specified by `body`, form paramters specified in `form`, and headers specified in `headers`, then return the response body as a string. Note: in order to conform with HTTP2+ all header names are transmuted to lowercase. Other Note: if a `body` and a `form` are supplied the value of `body` will be used. diff --git a/implants/lib/eldritch/src/http/download_impl.rs b/implants/lib/eldritch/src/http/download_impl.rs index 294526b72..6057d4854 100644 --- a/implants/lib/eldritch/src/http/download_impl.rs +++ b/implants/lib/eldritch/src/http/download_impl.rs @@ -3,7 +3,7 @@ use std::path::PathBuf; use tokio::{fs::File, io::AsyncWriteExt}; use tokio_stream::StreamExt; -async fn handle_download(uri: String, dst: String) -> Result<()> { +async fn handle_download(uri: String, dst: String, allow_insecure: bool) -> Result<()> { // Create our file let mut dest = { let fname = PathBuf::from(dst); @@ -12,7 +12,10 @@ async fn handle_download(uri: String, dst: String) -> Result<()> { // Download as a stream of bytes. // there's no checking at all happening here, for anything - let mut stream = reqwest::get(uri).await?.bytes_stream(); + let client = reqwest::Client::builder() + .danger_accept_invalid_certs(allow_insecure) + .build()?; + let mut stream = client.get(uri).send().await?.bytes_stream(); // Write the stream of bytes to the file in chunks while let Some(chunk_result) = stream.next().await { @@ -25,12 +28,17 @@ async fn handle_download(uri: String, dst: String) -> Result<()> { Ok(()) } -pub fn download(uri: String, dst: String) -> Result<()> { +pub fn download(uri: String, dst: String, allow_insecure: Option) -> Result<()> { let runtime = tokio::runtime::Builder::new_current_thread() .enable_all() .build()?; - let response = runtime.block_on(handle_download(uri, dst)); + let mut insecure = false; + if let Some(a) = allow_insecure { + insecure = a; + } + + let response = runtime.block_on(handle_download(uri, dst, insecure)); match response { Ok(_) => Ok(()), @@ -63,7 +71,7 @@ mod tests { let url = server.url("/foo").to_string(); // run our code - download(url, path.clone())?; + download(url, path.clone(), None)?; // Read the file let contents = read_to_string(path.clone())?; diff --git a/implants/lib/eldritch/src/http/get_impl.rs b/implants/lib/eldritch/src/http/get_impl.rs index e724d3f3a..1a469f6e6 100644 --- a/implants/lib/eldritch/src/http/get_impl.rs +++ b/implants/lib/eldritch/src/http/get_impl.rs @@ -7,12 +7,10 @@ pub fn get( uri: String, query_params: Option>, headers: Option>, + allow_insecure: Option, ) -> Result { let mut query_map = HashMap::new(); let mut headers_map = HeaderMap::new(); - let runtime = tokio::runtime::Builder::new_current_thread() - .enable_all() - .build()?; if let Some(q) = query_params { for (k, v) in q { @@ -28,26 +26,25 @@ pub fn get( } } - runtime.block_on(handle_get(uri, query_map, headers_map)) -} - -async fn handle_get( - uri: String, - query_params: HashMap, - headers: HeaderMap, -) -> Result { #[cfg(debug_assertions)] log::info!( - "eldritch sending HTTP GET request to '{}' with headers '{:#?}'", + "eldritch sending HTTP GET request to '{}' with headers '{:#?}' and query_params '{:#?}'", uri, - headers + headers_map, + query_map ); - let client = reqwest::Client::new() - .get(uri) - .headers(headers) - .query(&query_params); - let resp = client.send().await?.text().await?; + let mut insecure = false; + if let Some(a) = allow_insecure { + insecure = a; + } + + let client = reqwest::blocking::Client::builder() + .danger_accept_invalid_certs(insecure) + .build()?; + + let req = client.get(uri).headers(headers_map).query(&query_map); + let resp = req.send()?.text()?; Ok(resp) } @@ -71,7 +68,7 @@ mod tests { let url = server.url("/foo").to_string(); // run our code - let contents = get(url, None, None)?; + let contents = get(url, None, None, None)?; // check request returned correctly assert_eq!(contents, "test body"); @@ -92,7 +89,7 @@ mod tests { let url = server.url("/foo").to_string(); // run our code - let contents = get(url, Some(SmallMap::new()), Some(SmallMap::new()))?; + let contents = get(url, Some(SmallMap::new()), Some(SmallMap::new()), None)?; // check request returned correctly assert_eq!(contents, "test body"); @@ -120,7 +117,7 @@ mod tests { params.insert("a".to_string(), "true".to_string()); params.insert("b".to_string(), "bar".to_string()); params.insert("c".to_string(), "3".to_string()); - let contents = get(url, Some(params), None)?; + let contents = get(url, Some(params), None, None)?; // check request returned correctly assert_eq!(contents, "test body"); @@ -147,7 +144,7 @@ mod tests { let mut params = SmallMap::new(); params.insert("b".to_string(), "bar".to_string()); params.insert("c".to_string(), "3".to_string()); - let contents = get(url, Some(params), None)?; + let contents = get(url, Some(params), None, None)?; // check request returned correctly assert_eq!(contents, "test body"); @@ -173,7 +170,7 @@ mod tests { let mut headers = SmallMap::new(); headers.insert("A".to_string(), "TRUE".to_string()); headers.insert("b".to_string(), "bar".to_string()); - let contents = get(url, None, Some(headers))?; + let contents = get(url, None, Some(headers), None)?; // check request returned correctly assert_eq!(contents, "test body"); @@ -202,7 +199,7 @@ mod tests { headers.insert("b".to_string(), "bar".to_string()); let mut params = SmallMap::new(); params.insert("c".to_string(), "3".to_string()); - let contents = get(url, Some(params), Some(headers))?; + let contents = get(url, Some(params), Some(headers), None)?; // check request returned correctly assert_eq!(contents, "test body"); diff --git a/implants/lib/eldritch/src/http/mod.rs b/implants/lib/eldritch/src/http/mod.rs index 148013415..6069087b7 100644 --- a/implants/lib/eldritch/src/http/mod.rs +++ b/implants/lib/eldritch/src/http/mod.rs @@ -23,18 +23,18 @@ crate::eldritch_lib!(HTTPLibrary, "http_library"); #[allow(clippy::needless_lifetimes, clippy::type_complexity, clippy::too_many_arguments)] fn methods(builder: &mut MethodsBuilder) { #[allow(unused_variables)] - fn download(this: &HTTPLibrary, uri: String, dst: String) -> anyhow::Result { - download_impl::download(uri, dst)?; + fn download(this: &HTTPLibrary, uri: String, dst: String, allow_insecure: Option) -> anyhow::Result { + download_impl::download(uri, dst, allow_insecure)?; Ok(NoneType{}) } #[allow(unused_variables)] - fn get(this: &HTTPLibrary, uri: String, query_params: Option>, headers: Option>) -> anyhow::Result { - get_impl::get(uri, query_params, headers) + fn get(this: &HTTPLibrary, uri: String, query_params: Option>, headers: Option>, allow_insecure: Option) -> anyhow::Result { + get_impl::get(uri, query_params, headers, allow_insecure) } #[allow(unused_variables)] - fn post(this: &HTTPLibrary, uri: String, body: Option, form: Option>, headers: Option>) -> anyhow::Result { - post_impl::post(uri, body, form, headers) + fn post(this: &HTTPLibrary, uri: String, body: Option, form: Option>, headers: Option>, allow_insecure: Option) -> anyhow::Result { + post_impl::post(uri, body, form, headers, allow_insecure) } } diff --git a/implants/lib/eldritch/src/http/post_impl.rs b/implants/lib/eldritch/src/http/post_impl.rs index 091d32b88..d10f97e95 100644 --- a/implants/lib/eldritch/src/http/post_impl.rs +++ b/implants/lib/eldritch/src/http/post_impl.rs @@ -8,11 +8,9 @@ pub fn post( body: Option, form: Option>, headers: Option>, + allow_insecure: Option, ) -> Result { let mut headers_map = HeaderMap::new(); - let runtime = tokio::runtime::Builder::new_current_thread() - .enable_all() - .build()?; if let Some(h) = headers { for (k, v) in h { @@ -22,8 +20,27 @@ pub fn post( } } - if body.is_some() { - return runtime.block_on(handle_post(uri, body, None, headers_map)); + let mut insecure = false; + if let Some(a) = allow_insecure { + insecure = a; + } + + let client = reqwest::blocking::Client::builder() + .danger_accept_invalid_certs(insecure) + .build()?; + let req = client.post(uri.clone()).headers(headers_map.clone()); + + if let Some(b) = body { + #[cfg(debug_assertions)] + log::info!( + "eldritch sending HTTP POST request to '{}' with headers '{:#?}' and body '{}'", + uri, + headers_map, + b.clone() + ); + + let resp = req.body(b).send()?.text()?; + return Ok(resp); } if let Some(f) = form { @@ -32,35 +49,26 @@ pub fn post( form_map.insert(k, v); } - return runtime.block_on(handle_post(uri, None, Some(form_map), headers_map)); - } + #[cfg(debug_assertions)] + log::info!( + "eldritch sending HTTP POST request to '{}' with headers '{:#?}' and form '{:#?}'", + uri, + headers_map, + form_map.clone() + ); - runtime.block_on(handle_post(uri, None, None, headers_map)) -} + let resp = req.form(&form_map).send()?.text()?; + return Ok(resp); + } -async fn handle_post( - uri: String, - body: Option, - form: Option>, - headers: HeaderMap, -) -> Result { #[cfg(debug_assertions)] log::info!( "eldritch sending HTTP POST request to '{}' with headers '{:#?}'", uri, - headers + headers_map ); - let client = reqwest::Client::new().post(uri).headers(headers); - if let Some(b) = body { - let resp = client.body(b).send().await?.text().await?; - return Ok(resp); - } - if let Some(f) = form { - let resp = client.form(&f).send().await?.text().await?; - return Ok(resp); - } - let resp = client.send().await?.text().await?; + let resp = req.send()?.text()?; Ok(resp) } @@ -84,7 +92,7 @@ mod tests { let url = server.url("/foo").to_string(); // run our code - let contents = post(url, None, None, None)?; + let contents = post(url, None, None, None, None)?; // check request returned correctly assert_eq!(contents, "test body"); @@ -105,7 +113,13 @@ mod tests { let url = server.url("/foo").to_string(); // run our code - let contents = post(url, None, Some(SmallMap::new()), Some(SmallMap::new()))?; + let contents = post( + url, + None, + Some(SmallMap::new()), + Some(SmallMap::new()), + None, + )?; // check request returned correctly assert_eq!(contents, "test body"); @@ -133,7 +147,7 @@ mod tests { params.insert("a".to_string(), "true".to_string()); params.insert("b".to_string(), "bar".to_string()); params.insert("c".to_string(), "3".to_string()); - let contents = post(url, None, Some(params), None)?; + let contents = post(url, None, Some(params), None, None)?; // check request returned correctly assert_eq!(contents, "test body"); @@ -159,7 +173,7 @@ mod tests { let mut headers = SmallMap::new(); headers.insert("A".to_string(), "TRUE".to_string()); headers.insert("b".to_string(), "bar".to_string()); - let contents = post(url, None, None, Some(headers))?; + let contents = post(url, None, None, Some(headers), None)?; // check request returned correctly assert_eq!(contents, "test body"); @@ -188,7 +202,7 @@ mod tests { headers.insert("b".to_string(), "bar".to_string()); let mut params = SmallMap::new(); params.insert("c".to_string(), "3".to_string()); - let contents = post(url, None, Some(params), Some(headers))?; + let contents = post(url, None, Some(params), Some(headers), None)?; // check request returned correctly assert_eq!(contents, "test body"); @@ -218,6 +232,7 @@ mod tests { Some(String::from("the quick brown fox jumps over the lazy dog")), None, Some(headers), + None, )?; // check request returned correctly