diff --git a/dtrfs_api/Cargo.lock b/dtrfs_api/Cargo.lock index d73b5bd..d4295c9 100644 --- a/dtrfs_api/Cargo.lock +++ b/dtrfs_api/Cargo.lock @@ -671,6 +671,7 @@ dependencies = [ "base64", "bincode", "ed25519-dalek", + "futures", "lazy_static", "regex", "rustls", @@ -678,9 +679,6 @@ dependencies = [ "serde", "sev", "sha3", - "tokio", - "tokio-stream", - "tokio-util", ] [[package]] @@ -832,12 +830,65 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + [[package]] name = "futures-core" version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "futures-sink" version = "0.3.31" @@ -856,10 +907,16 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ + "futures-channel", "futures-core", + "futures-io", + "futures-macro", + "futures-sink", "futures-task", + "memchr", "pin-project-lite", "pin-utils", + "slab", ] [[package]] @@ -2119,21 +2176,9 @@ dependencies = [ "pin-project-lite", "signal-hook-registry", "socket2", - "tokio-macros", "windows-sys 0.52.0", ] -[[package]] -name = "tokio-macros" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "tokio-rustls" version = "0.26.0" @@ -2145,17 +2190,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-stream" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", -] - [[package]] name = "tokio-util" version = "0.7.13" diff --git a/dtrfs_api/Cargo.toml b/dtrfs_api/Cargo.toml index 2f66da4..2c4e624 100644 --- a/dtrfs_api/Cargo.toml +++ b/dtrfs_api/Cargo.toml @@ -11,9 +11,7 @@ regex = "1.11.1" sev = { version = "4.0", default-features = false, features = ['crypto_nossl','snp'] } ed25519-dalek = { version = "2.1.1", features = ["pem", "pkcs8"] } lazy_static = "1.5.0" -tokio = { version = "1.42.0", features = ["full"] } -tokio-util = "0.7.13" -tokio-stream = { version = "0.1.17", features = ["io-util"] } +futures = "0.3.31" actix-web = { version = "4.9.0", features = ["rustls-0_23"] } sha3 = "0.10.8" rustls = "0.23.18" diff --git a/dtrfs_api/src/main.rs b/dtrfs_api/src/main.rs index b174538..e93b31f 100644 --- a/dtrfs_api/src/main.rs +++ b/dtrfs_api/src/main.rs @@ -94,7 +94,10 @@ async fn post_install_form(req: HttpRequest, form: web::Form) -> Ht return HttpResponse::BadRequest().body(format!("Signature verification failed: {}", e)); }; match os::encrypt_and_install_os(&form.url, &form.sha, &form.keyfile).await { - Ok(s) => s, + Ok(s) => { + let stream = futures::stream::iter(s.map(|item| item.map(|s| actix_web::web::Bytes::from(s)))); + HttpResponse::Ok().content_type("text/plain; charset=utf-8").streaming(stream) + }, Err(e) => HttpResponse::InternalServerError().body(format!("{e:?}")), } } diff --git a/dtrfs_api/src/os.rs b/dtrfs_api/src/os.rs index 32d3c1d..a7d0c8e 100644 --- a/dtrfs_api/src/os.rs +++ b/dtrfs_api/src/os.rs @@ -1,14 +1,14 @@ use crate::snp::get_derived_key; -use actix_web::{web::Bytes, HttpResponse}; use anyhow::{anyhow, Result}; use base64::prelude::{Engine, BASE64_URL_SAFE}; -use std::process::Command; use std::{ - fs::File, - io::{BufRead, BufReader, Write}, + fs::{self, File}, + io::{self, BufRead, BufReader, Write}, path::Path, - process::Stdio, + process::{Command, Stdio}, }; +use std::thread; +use std::sync::mpsc::{self, Sender, Receiver}; const SNP_KEYFILE_PATH: &str = "/tmp/detee_snp_keyfile"; const BACKUP_KEYFILE_PATH: &str = "/tmp/detee_backup_keyfile"; @@ -17,18 +17,14 @@ pub async fn encrypt_and_install_os( install_url: &str, install_sha: &str, keyfile: &str, -) -> Result { - use tokio::process::Command; - use tokio::io::{BufReader, AsyncBufReadExt}; - use tokio_stream::{StreamExt, wrappers::LinesStream}; +) -> Result>, Box> { + // Decode the keyfile from base64 + let binary_keyfile = BASE64_URL_SAFE.decode(keyfile)?; + fs::write(BACKUP_KEYFILE_PATH, binary_keyfile.clone())?; - let binary_keyfile = base64::engine::general_purpose::URL_SAFE.decode(keyfile) - .map_err(|e| actix_web::error::ErrorBadRequest(e.to_string()))?; - - // Write the decoded keyfile to the backup path asynchronously - tokio::fs::write(BACKUP_KEYFILE_PATH, &binary_keyfile) - .await - .map_err(|e| actix_web::error::ErrorInternalServerError(e.to_string()))?; + // Write the decoded keyfile to the backup path + let mut backup_keyfile = File::create(BACKUP_KEYFILE_PATH)?; + backup_keyfile.write_all(&binary_keyfile)?; // Spawn the installation script as a child process let mut child = Command::new("/usr/lib/dtrfs/install_os.sh") @@ -38,30 +34,32 @@ pub async fn encrypt_and_install_os( .env("ROOT_KEYFILE", BACKUP_KEYFILE_PATH) .stdout(Stdio::piped()) .stderr(Stdio::piped()) - .spawn() - .map_err(|e| actix_web::error::ErrorInternalServerError(e.to_string()))?; + .spawn()?; // Take stdout and stderr from the child process - let stdout = child.stdout.take().ok_or_else(|| { - actix_web::error::ErrorInternalServerError("Failed to capture stdout".to_string()) - })?; - let stderr = child.stderr.take().ok_or_else(|| { - actix_web::error::ErrorInternalServerError("Failed to capture stderr".to_string()) - })?; + let stdout = child.stdout.take().ok_or("Failed to capture stdout")?; + let stderr = child.stderr.take().ok_or("Failed to capture stderr")?; - // Merge stdout and stderr into a single stream - let stdout_lines = LinesStream::new(BufReader::new(stdout).lines()); - let stderr_lines = LinesStream::new(BufReader::new(stderr).lines()); - let merged_stream = stdout_lines.merge(stderr_lines).map(|line_result| { - line_result - .map(|line| Bytes::from(line + "\n")) - .map_err(|e| actix_web::error::ErrorInternalServerError(e.to_string())) - }); + // Create channels to receive lines from stdout and stderr + let (tx, rx): (Sender>, Receiver>) = mpsc::channel(); - // Return the merged stream as the HTTP response - Ok(HttpResponse::Ok() - .content_type("text/plain; charset=utf-8") - .streaming(merged_stream)) + // Function to read lines from a reader and send them through a channel + fn read_lines(reader: R, sender: Sender>) { + thread::spawn(move || { + for line in reader.lines() { + if sender.send(line).is_err() { + break; + } + } + }); + } + + // Start threads to read stdout and stderr + read_lines(BufReader::new(stdout), tx.clone()); + read_lines(BufReader::new(stderr), tx); + + // Return an iterator over the received lines + Ok(rx.into_iter()) } pub fn try_hot_keyfile() -> Result<()> {