diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 8e16c8cb97..779378d12c 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -197,9 +197,9 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" [[package]] name = "base64ct" -version = "1.0.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a32fd6af2b5827bce66c29053ba0e7c42b9dcab01835835058558c10851a46b" +checksum = "dea908e7347a8c64e378c17e30ef880ad73e3b4498346b055c2c00ea342f3179" [[package]] name = "basic-cookies" @@ -530,6 +530,12 @@ dependencies = [ "tracing-error", ] +[[package]] +name = "const-oid" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "722e23542a15cea1f65d4a1419c4cfd7a26706c70871a13a04238ca3f40f1661" + [[package]] name = "const_fn" version = "0.4.9" @@ -694,9 +700,9 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "3.2.1" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0" +checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" dependencies = [ "byteorder", "digest 0.9.0", @@ -856,6 +862,17 @@ dependencies = [ "syn 1.0.96", ] +[[package]] +name = "der" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dd2ae565c0a381dde7fade45fce95984c568bdcb4700a4fdbe3175e0380b2f" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + [[package]] name = "derive_more" version = "0.99.17" @@ -892,6 +909,7 @@ checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" dependencies = [ "block-buffer 0.10.2", "crypto-common", + "subtle", ] [[package]] @@ -965,6 +983,7 @@ version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9c280362032ea4203659fc489832d0204ef09f247a0506f170dafcac08c369" dependencies = [ + "pkcs8", "serde", "signature", ] @@ -1002,6 +1021,7 @@ dependencies = [ "avahi-sys", "base32", "base64 0.13.0", + "base64ct", "basic-cookies", "bollard", "chrono", @@ -1009,8 +1029,10 @@ dependencies = [ "clap", "color-eyre", "cookie_store", + "digest 0.10.3", "digest 0.9.0", "divrem", + "ed25519", "ed25519-dalek", "emver", "fd-lock-rs", @@ -1018,7 +1040,7 @@ dependencies = [ "git-version", "helpers", "hex", - "hmac", + "hmac 0.12.1", "http", "hyper", "hyper-ws-listener", @@ -1041,6 +1063,7 @@ dependencies = [ "patch-db", "pbkdf2", "pin-project", + "pkcs8", "platforms", "prettytable-rs", "proptest", @@ -1057,6 +1080,7 @@ dependencies = [ "serde_json", "serde_with", "serde_yaml", + "sha2 0.10.2", "sha2 0.9.9", "simple-logging", "sqlx", @@ -1552,6 +1576,15 @@ dependencies = [ "digest 0.9.0", ] +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.3", +] + [[package]] name = "http" version = "0.2.7" @@ -2502,9 +2535,9 @@ dependencies = [ [[package]] name = "password-hash" -version = "0.3.2" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d791538a6dcc1e7cb7fe6f6b58aca40e7f79403c45b2bc274008b5e647af1d8" +checksum = "e029e94abc8fb0065241c308f1ac6bc8d20f450e8f7c5f0b25cd9b8d526ba294" dependencies = [ "base64ct", "rand_core 0.6.3", @@ -2560,14 +2593,14 @@ dependencies = [ [[package]] name = "pbkdf2" -version = "0.9.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f05894bce6a1ba4be299d0c5f29563e08af2bc18bb7d48313113bed71e904739" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ - "crypto-mac", - "hmac", + "digest 0.10.3", + "hmac 0.12.1", "password-hash", - "sha2 0.9.9", + "sha2 0.10.2", ] [[package]] @@ -2576,6 +2609,15 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" +[[package]] +name = "pem-rfc7468" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d159833a9105500e0398934e205e0773f0b27529557134ecfc51c27646adac" +dependencies = [ + "base64ct", +] + [[package]] name = "percent-encoding" version = "2.1.0" @@ -2680,6 +2722,16 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs8" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" +dependencies = [ + "der", + "spki", +] + [[package]] name = "pkg-config" version = "0.3.25" @@ -3583,6 +3635,16 @@ dependencies = [ "lock_api", ] +[[package]] +name = "spki" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "sqlformat" version = "0.1.8" @@ -4584,7 +4646,7 @@ dependencies = [ "derive_more", "ed25519-dalek", "hex", - "hmac", + "hmac 0.11.0", "rand 0.7.3", "serde", "serde_derive", @@ -5152,9 +5214,9 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.3.0" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" +checksum = "94693807d016b2f2d2e14420eb3bfcca689311ff775dcf113d74ea624b7cdf07" dependencies = [ "zeroize_derive", ] diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 6e0b8463ff..4dc6282cf3 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -53,21 +53,25 @@ avahi-sys = { git = "https://github.com/Start9Labs/avahi-sys", version = "0.10.0 ], optional = true } base32 = "0.4.0" base64 = "0.13.0" +base64ct = "1.5.0" basic-cookies = "0.1.4" bollard = "0.11.0" chrono = { version = "0.4.19", features = ["serde"] } clap = "2.33" color-eyre = "0.5" cookie_store = "0.15.0" -digest = "0.9.0" +digest = "0.10.3" +digest-old = { package = "digest", version = "0.9.0" } divrem = "1.0.0" +ed25519 = { version = "1.5.2", features = ["pkcs8", "pem", "alloc"] } ed25519-dalek = { version = "1.0.1", features = ["serde"] } emver = { version = "0.1.6", features = ["serde"] } fd-lock-rs = "0.1.3" futures = "0.3.17" git-version = "0.3.5" +helpers = { path = "../libs/helpers" } hex = "0.4.3" -hmac = "0.11.0" +hmac = "0.12.1" http = "0.2.5" hyper = "0.14.13" hyper-ws-listener = { git = "https://github.com/Start9Labs/hyper-ws-listener.git", branch = "main" } @@ -75,24 +79,24 @@ imbl = "1.0.1" indexmap = { version = "1.8.1", features = ["serde"] } isocountry = "0.3.2" itertools = "0.10.1" +js_engine = { path = '../libs/js_engine', optional = true } jsonpath_lib = "0.3.0" lazy_static = "1.4" libc = "0.2.103" log = "0.4.14" +models = { version = "*", path = "../libs/models" } nix = "0.23.0" nom = "7.0.0" -helpers = {path = "../libs/helpers"} num = "0.4.0" num_enum = "0.5.4" -models = {version = "*", path = "../libs/models"} -js_engine = {path = '../libs/js_engine', optional = true} openssh-keys = "0.5.0" openssl = { version = "0.10.36", features = ["vendored"] } patch-db = { version = "*", path = "../patch-db/patch-db", features = [ "trace", ] } -pbkdf2 = "0.9.0" +pbkdf2 = "0.11.0" pin-project = "1.0.8" +pkcs8 = { version = "0.9.0", features = ["std"] } platforms = "1.1.0" prettytable-rs = "0.8.0" proptest = "1.0.0" @@ -110,7 +114,8 @@ serde_cbor = { package = "ciborium", version = "0.2.0" } serde_json = "1.0.68" serde_toml = { package = "toml", version = "0.5.8" } serde_yaml = "0.8.21" -sha2 = "0.9.8" +sha2 = "0.10.2" +sha2-old = { package = "sha2", version = "0.9.8" } simple-logging = "2.0" sqlx = { version = "0.5.11", features = [ "chrono", diff --git a/backend/install-sdk.sh b/backend/install-sdk.sh index 223a7da88a..90425d9dd8 100755 --- a/backend/install-sdk.sh +++ b/backend/install-sdk.sh @@ -8,4 +8,4 @@ if [ "$0" != "./install-sdk.sh" ]; then exit 1 fi -cargo install --bin=embassy-sdk --path=. --no-default-features --features=js_engine +cargo install --bin=embassy-sdk --bin=embassy-cli --path=. --no-default-features --features=js_engine diff --git a/backend/src/backup/target/mod.rs b/backend/src/backup/target/mod.rs index 109432a74d..fb140c260e 100644 --- a/backend/src/backup/target/mod.rs +++ b/backend/src/backup/target/mod.rs @@ -6,7 +6,7 @@ use chrono::{DateTime, Utc}; use clap::ArgMatches; use color_eyre::eyre::eyre; use digest::generic_array::GenericArray; -use digest::Digest; +use digest::{Digest, OutputSizeUser}; use rpc_toolkit::command; use serde::{Deserialize, Serialize}; use sha2::Sha256; @@ -119,7 +119,9 @@ impl FileSystem for BackupTargetFS { BackupTargetFS::Cifs(a) => a.mount(mountpoint, mount_type).await, } } - async fn source_hash(&self) -> Result::OutputSize>, Error> { + async fn source_hash( + &self, + ) -> Result::OutputSize>, Error> { match self { BackupTargetFS::Disk(a) => a.source_hash().await, BackupTargetFS::Cifs(a) => a.source_hash().await, diff --git a/backend/src/context/cli.rs b/backend/src/context/cli.rs index 0996f87f80..8981b1efec 100644 --- a/backend/src/context/cli.rs +++ b/backend/src/context/cli.rs @@ -15,6 +15,7 @@ use rpc_toolkit::Context; use serde::Deserialize; use tracing::instrument; +use crate::util::config::{load_config_from_paths, local_config_path}; use crate::ResultExt; #[derive(Debug, Default, Deserialize)] @@ -60,16 +61,16 @@ impl CliContext { /// BLOCKING #[instrument(skip(matches))] pub fn init(matches: &ArgMatches) -> Result { - let cfg_path = Path::new(matches.value_of("config").unwrap_or(crate::CONFIG_PATH)); - let base = if cfg_path.exists() { - serde_yaml::from_reader( - File::open(cfg_path) - .with_ctx(|_| (crate::ErrorKind::Filesystem, cfg_path.display().to_string()))?, - ) - .with_kind(crate::ErrorKind::Deserialization)? - } else { - CliContextConfig::default() - }; + let local_config_path = local_config_path(); + let base: CliContextConfig = load_config_from_paths( + matches + .values_of("config") + .into_iter() + .flatten() + .map(|p| Path::new(p)) + .chain(local_config_path.as_deref().into_iter()) + .chain(std::iter::once(Path::new(crate::util::config::CONFIG_PATH))), + )?; let mut url = if let Some(host) = matches.value_of("host") { host.parse()? } else if let Some(host) = base.host { @@ -88,7 +89,9 @@ impl CliContext { }; let cookie_path = base.cookie_path.unwrap_or_else(|| { - cfg_path + local_config_path + .as_deref() + .unwrap_or_else(|| Path::new(crate::util::config::CONFIG_PATH)) .parent() .unwrap_or(Path::new("/")) .join(".cookies.json") diff --git a/backend/src/context/diagnostic.rs b/backend/src/context/diagnostic.rs index 36ea6fe703..025179829f 100644 --- a/backend/src/context/diagnostic.rs +++ b/backend/src/context/diagnostic.rs @@ -28,7 +28,7 @@ impl DiagnosticContextConfig { let cfg_path = path .as_ref() .map(|p| p.as_ref()) - .unwrap_or(Path::new(crate::CONFIG_PATH)); + .unwrap_or(Path::new(crate::util::config::CONFIG_PATH)); if let Some(f) = File::maybe_open(cfg_path) .await .with_ctx(|_| (crate::ErrorKind::Filesystem, cfg_path.display().to_string()))? diff --git a/backend/src/context/rpc.rs b/backend/src/context/rpc.rs index 40659f2092..a5e99b9e36 100644 --- a/backend/src/context/rpc.rs +++ b/backend/src/context/rpc.rs @@ -7,8 +7,8 @@ use std::sync::Arc; use std::time::Duration; use bollard::Docker; -use patch_db::{json_ptr::JsonPointer, LockReceipt}; -use patch_db::{DbHandle, LockType, PatchDb, Revision}; +use patch_db::json_ptr::JsonPointer; +use patch_db::{DbHandle, LockReceipt, LockType, PatchDb, Revision}; use reqwest::Url; use rpc_toolkit::url::Host; use rpc_toolkit::Context; @@ -20,9 +20,10 @@ use tokio::process::Command; use tokio::sync::{broadcast, oneshot, Mutex, RwLock}; use tracing::instrument; +use crate::core::rpc_continuations::{RequestGuid, RpcContinuation}; use crate::db::model::{Database, InstalledPackageDataEntry, PackageDataEntry}; use crate::hostname::{derive_hostname, derive_id, get_product_key}; -use crate::install::cleanup::{cleanup_failed, uninstall}; +use crate::install::cleanup::{cleanup_failed, uninstall, CleanupFailedReceipts}; use crate::manager::ManagerMap; use crate::middleware::auth::HashSessionToken; use crate::net::tor::os_key; @@ -34,10 +35,6 @@ use crate::shutdown::Shutdown; use crate::status::{MainStatus, Status}; use crate::util::io::from_yaml_async_reader; use crate::util::{AsyncFileExt, Invoke}; -use crate::{ - core::rpc_continuations::{RequestGuid, RpcContinuation}, - install::cleanup::CleanupFailedReceipts, -}; use crate::{Error, ResultExt}; #[derive(Debug, Default, Deserialize)] @@ -57,7 +54,7 @@ impl RpcContextConfig { let cfg_path = path .as_ref() .map(|p| p.as_ref()) - .unwrap_or(Path::new(crate::CONFIG_PATH)); + .unwrap_or(Path::new(crate::util::config::CONFIG_PATH)); if let Some(f) = File::maybe_open(cfg_path) .await .with_ctx(|_| (crate::ErrorKind::Filesystem, cfg_path.display().to_string()))? diff --git a/backend/src/context/sdk.rs b/backend/src/context/sdk.rs index 853ee71dc0..a4924d1ce9 100644 --- a/backend/src/context/sdk.rs +++ b/backend/src/context/sdk.rs @@ -1,5 +1,3 @@ -use std::fs::File; -use std::io::Read; use std::path::{Path, PathBuf}; use std::sync::Arc; @@ -9,6 +7,7 @@ use rpc_toolkit::Context; use serde::Deserialize; use tracing::instrument; +use crate::util::config::{load_config_from_paths, local_config_path}; use crate::{Error, ResultExt}; #[derive(Debug, Default, Deserialize)] @@ -28,22 +27,24 @@ impl SdkContext { /// BLOCKING #[instrument(skip(matches))] pub fn init(matches: &ArgMatches) -> Result { - let cfg_path = Path::new(matches.value_of("config").unwrap_or(crate::CONFIG_PATH)); - let base = if cfg_path.exists() { - serde_yaml::from_reader( - File::open(cfg_path) - .with_ctx(|_| (crate::ErrorKind::Filesystem, cfg_path.display().to_string()))?, - ) - .with_kind(crate::ErrorKind::Deserialization)? - } else { - SdkContextConfig::default() - }; + let local_config_path = local_config_path(); + let base: SdkContextConfig = load_config_from_paths( + matches + .values_of("config") + .into_iter() + .flatten() + .map(|p| Path::new(p)) + .chain(local_config_path.as_deref().into_iter()) + .chain(std::iter::once(Path::new(crate::util::config::CONFIG_PATH))), + )?; Ok(SdkContext(Arc::new(SdkContextSeed { developer_key_path: base.developer_key_path.unwrap_or_else(|| { - cfg_path + local_config_path + .as_deref() + .unwrap_or_else(|| Path::new(crate::util::config::CONFIG_PATH)) .parent() .unwrap_or(Path::new("/")) - .join(".developer_key") + .join("developer.key.pem") }), }))) } @@ -53,9 +54,17 @@ impl SdkContext { if !self.developer_key_path.exists() { return Err(Error::new(eyre!("Developer Key does not exist! Please run `embassy-sdk init` before running this command."), crate::ErrorKind::Uninitialized)); } - let mut keypair_buf = [0; ed25519_dalek::KEYPAIR_LENGTH]; - File::open(&self.developer_key_path)?.read_exact(&mut keypair_buf)?; - Ok(ed25519_dalek::Keypair::from_bytes(&keypair_buf)?) + let pair = ::from_pkcs8_pem( + &std::fs::read_to_string(&self.developer_key_path)?, + ) + .with_kind(crate::ErrorKind::Pem)?; + let secret = ed25519_dalek::SecretKey::from_bytes(&pair.secret_key[..])?; + let public = if let Some(public) = pair.public_key { + ed25519_dalek::PublicKey::from_bytes(&public[..])? + } else { + (&secret).into() + }; + Ok(ed25519_dalek::Keypair { secret, public }) } } impl std::ops::Deref for SdkContext { diff --git a/backend/src/context/setup.rs b/backend/src/context/setup.rs index 8b9b2b614a..8fd1187830 100644 --- a/backend/src/context/setup.rs +++ b/backend/src/context/setup.rs @@ -45,7 +45,7 @@ impl SetupContextConfig { let cfg_path = path .as_ref() .map(|p| p.as_ref()) - .unwrap_or(Path::new(crate::CONFIG_PATH)); + .unwrap_or(Path::new(crate::util::config::CONFIG_PATH)); if let Some(f) = File::maybe_open(cfg_path) .await .with_ctx(|_| (crate::ErrorKind::Filesystem, cfg_path.display().to_string()))? diff --git a/backend/src/developer/mod.rs b/backend/src/developer/mod.rs index bf2ded3c3c..ce169d2cc3 100644 --- a/backend/src/developer/mod.rs +++ b/backend/src/developer/mod.rs @@ -2,6 +2,7 @@ use std::fs::File; use std::io::Write; use std::path::Path; +use ed25519::pkcs8::EncodePrivateKey; use ed25519_dalek::Keypair; use rpc_toolkit::command; use tracing::instrument; @@ -22,8 +23,17 @@ pub fn init(#[context] ctx: SdkContext) -> Result<(), Error> { tracing::info!("Generating new developer key..."); let keypair = Keypair::generate(&mut rand::thread_rng()); tracing::info!("Writing key to {}", ctx.developer_key_path.display()); + let keypair_bytes = ed25519::KeypairBytes { + secret_key: keypair.secret.to_bytes(), + public_key: Some(keypair.public.to_bytes()), + }; let mut dev_key_file = File::create(&ctx.developer_key_path)?; - dev_key_file.write_all(&keypair.to_bytes())?; + dev_key_file.write_all( + keypair_bytes + .to_pkcs8_pem(base64ct::LineEnding::default()) + .with_kind(crate::ErrorKind::Pem)? + .as_bytes(), + )?; dev_key_file.sync_all()?; } Ok(()) diff --git a/backend/src/disk/mount/filesystem/block_dev.rs b/backend/src/disk/mount/filesystem/block_dev.rs index 468baa4755..e21f0c42d3 100644 --- a/backend/src/disk/mount/filesystem/block_dev.rs +++ b/backend/src/disk/mount/filesystem/block_dev.rs @@ -3,7 +3,7 @@ use std::path::Path; use async_trait::async_trait; use digest::generic_array::GenericArray; -use digest::Digest; +use digest::{Digest, OutputSizeUser}; use serde::{Deserialize, Serialize}; use sha2::Sha256; @@ -45,7 +45,9 @@ impl + Send + Sync> FileSystem for BlockDev Result<(), Error> { mount(self.logicalname.as_ref(), mountpoint, mount_type).await } - async fn source_hash(&self) -> Result::OutputSize>, Error> { + async fn source_hash( + &self, + ) -> Result::OutputSize>, Error> { let mut sha = Sha256::new(); sha.update("BlockDev"); sha.update( diff --git a/backend/src/disk/mount/filesystem/cifs.rs b/backend/src/disk/mount/filesystem/cifs.rs index d87c94c3ec..b7e9ddf02e 100644 --- a/backend/src/disk/mount/filesystem/cifs.rs +++ b/backend/src/disk/mount/filesystem/cifs.rs @@ -4,7 +4,7 @@ use std::path::{Path, PathBuf}; use async_trait::async_trait; use digest::generic_array::GenericArray; -use digest::Digest; +use digest::{Digest, OutputSizeUser}; use serde::{Deserialize, Serialize}; use sha2::Sha256; use tokio::process::Command; @@ -93,7 +93,9 @@ impl FileSystem for Cifs { ) .await } - async fn source_hash(&self) -> Result::OutputSize>, Error> { + async fn source_hash( + &self, + ) -> Result::OutputSize>, Error> { let mut sha = Sha256::new(); sha.update("Cifs"); sha.update(self.hostname.as_bytes()); diff --git a/backend/src/disk/mount/filesystem/ecryptfs.rs b/backend/src/disk/mount/filesystem/ecryptfs.rs index f98a24fcdb..3c828f4c76 100644 --- a/backend/src/disk/mount/filesystem/ecryptfs.rs +++ b/backend/src/disk/mount/filesystem/ecryptfs.rs @@ -4,7 +4,7 @@ use std::path::Path; use async_trait::async_trait; use color_eyre::eyre::eyre; use digest::generic_array::GenericArray; -use digest::Digest; +use digest::{Digest, OutputSizeUser}; use sha2::Sha256; use tokio::io::{AsyncReadExt, AsyncWriteExt}; @@ -63,7 +63,9 @@ impl + Send + Sync, Key: AsRef + Send + Sync> Fil ) -> Result<(), Error> { mount_ecryptfs(self.encrypted_dir.as_ref(), mountpoint, self.key.as_ref()).await } - async fn source_hash(&self) -> Result::OutputSize>, Error> { + async fn source_hash( + &self, + ) -> Result::OutputSize>, Error> { let mut sha = Sha256::new(); sha.update("EcryptFS"); sha.update( diff --git a/backend/src/disk/mount/filesystem/label.rs b/backend/src/disk/mount/filesystem/label.rs index 40b606c8aa..b1e4f72134 100644 --- a/backend/src/disk/mount/filesystem/label.rs +++ b/backend/src/disk/mount/filesystem/label.rs @@ -2,7 +2,7 @@ use std::path::Path; use async_trait::async_trait; use digest::generic_array::GenericArray; -use digest::Digest; +use digest::{Digest, OutputSizeUser}; use sha2::Sha256; use super::{FileSystem, MountType, ReadOnly}; @@ -41,7 +41,9 @@ impl + Send + Sync> FileSystem for Label { ) -> Result<(), Error> { mount_label(self.label.as_ref(), mountpoint, mount_type).await } - async fn source_hash(&self) -> Result::OutputSize>, Error> { + async fn source_hash( + &self, + ) -> Result::OutputSize>, Error> { let mut sha = Sha256::new(); sha.update("Label"); sha.update(self.label.as_ref().as_bytes()); diff --git a/backend/src/disk/mount/filesystem/mod.rs b/backend/src/disk/mount/filesystem/mod.rs index 60cfd5d09d..f24383f3f7 100644 --- a/backend/src/disk/mount/filesystem/mod.rs +++ b/backend/src/disk/mount/filesystem/mod.rs @@ -2,7 +2,7 @@ use std::path::Path; use async_trait::async_trait; use digest::generic_array::GenericArray; -use digest::Digest; +use digest::{Digest, OutputSizeUser}; use sha2::Sha256; use crate::Error; @@ -27,5 +27,7 @@ pub trait FileSystem { mountpoint: P, mount_type: MountType, ) -> Result<(), Error>; - async fn source_hash(&self) -> Result::OutputSize>, Error>; + async fn source_hash( + &self, + ) -> Result::OutputSize>, Error>; } diff --git a/backend/src/error.rs b/backend/src/error.rs index c04a6d9887..3cc39a4588 100644 --- a/backend/src/error.rs +++ b/backend/src/error.rs @@ -31,7 +31,7 @@ pub enum ErrorKind { InvalidOnionAddress = 22, Pack = 23, ValidateS9pk = 24, - DiskCorrupted = 25, + DiskCorrupted = 25, // Remove Tor = 26, ConfigGen = 27, ParseNumber = 28, @@ -66,6 +66,7 @@ pub enum ErrorKind { ProductKeyMismatch = 57, LanPortConflict = 58, Javascript = 59, + Pem = 60, } impl ErrorKind { pub fn as_str(&self) -> &'static str { @@ -128,8 +129,9 @@ impl ErrorKind { Incoherent => "Incoherent", InvalidBackupTargetId => "Invalid Backup Target ID", ProductKeyMismatch => "Incompatible Product Keys", - LanPortConflict => "Incompatible LAN port configuration", - Javascript => "Javascript engine error", + LanPortConflict => "Incompatible LAN Port Configuration", + Javascript => "Javascript Engine Error", + Pem => "PEM Encoding Error", } } } diff --git a/backend/src/lib.rs b/backend/src/lib.rs index 9b592d0f6d..b4e61bb5af 100644 --- a/backend/src/lib.rs +++ b/backend/src/lib.rs @@ -1,4 +1,3 @@ -pub const CONFIG_PATH: &str = "/etc/embassy/config.yaml"; #[cfg(not(feature = "beta"))] pub const DEFAULT_MARKETPLACE: &str = "https://marketplace.start9.com"; #[cfg(feature = "beta")] diff --git a/backend/src/s9pk/builder.rs b/backend/src/s9pk/builder.rs index a973b4276b..28052a0860 100644 --- a/backend/src/s9pk/builder.rs +++ b/backend/src/s9pk/builder.rs @@ -1,5 +1,4 @@ -use digest::Digest; -use sha2::Sha512; +use sha2_old::{Digest, Sha512}; use tokio::io::{AsyncReadExt, AsyncSeekExt, AsyncWriteExt, SeekFrom}; use tracing::instrument; use typed_builder::TypedBuilder; diff --git a/backend/src/s9pk/reader.rs b/backend/src/s9pk/reader.rs index eb4043d27c..d8b04f1abd 100644 --- a/backend/src/s9pk/reader.rs +++ b/backend/src/s9pk/reader.rs @@ -6,10 +6,10 @@ use std::str::FromStr; use std::task::{Context, Poll}; use color_eyre::eyre::eyre; -use digest::Output; +use digest_old::Output; use ed25519_dalek::PublicKey; use futures::TryStreamExt; -use sha2::{Digest, Sha512}; +use sha2_old::{Digest, Sha512}; use tokio::fs::File; use tokio::io::{AsyncRead, AsyncReadExt, AsyncSeek, AsyncSeekExt, ReadBuf, Take}; use tracing::instrument; diff --git a/backend/src/setup.rs b/backend/src/setup.rs index 8cb1cc3f41..75565d88fc 100644 --- a/backend/src/setup.rs +++ b/backend/src/setup.rs @@ -7,6 +7,7 @@ use std::time::Duration; use color_eyre::eyre::eyre; use digest::generic_array::GenericArray; +use digest::OutputSizeUser; use futures::future::BoxFuture; use futures::{FutureExt, TryFutureExt, TryStreamExt}; use nix::unistd::{Gid, Uid}; @@ -477,7 +478,7 @@ async fn recover( async fn shasum( path: impl AsRef, -) -> Result::OutputSize>, Error> { +) -> Result::OutputSize>, Error> { use tokio::io::AsyncReadExt; let mut rdr = tokio::fs::File::open(path).await?; diff --git a/backend/src/util/config.rs b/backend/src/util/config.rs new file mode 100644 index 0000000000..ffdeaa7cc7 --- /dev/null +++ b/backend/src/util/config.rs @@ -0,0 +1,56 @@ +use std::fs::File; +use std::path::{Path, PathBuf}; + +use serde::Deserialize; +use serde_json::Value; + +use crate::util::serde::IoFormat; +use crate::{Config, Error, ResultExt}; + +pub const CONFIG_PATH: &str = "/etc/embassy/config.yaml"; +pub const CONFIG_PATH_LOCAL: &str = ".embassy/config.yaml"; + +pub fn local_config_path() -> Option { + if let Ok(home) = std::env::var("HOME") { + Some(Path::new(&home).join(CONFIG_PATH_LOCAL)) + } else { + None + } +} + +/// BLOCKING +pub fn load_config_from_paths<'a, T: for<'de> Deserialize<'de>>( + paths: impl IntoIterator>, +) -> Result { + let mut config = Default::default(); + for path in paths { + if path.as_ref().exists() { + let format: IoFormat = path + .as_ref() + .extension() + .and_then(|s| s.to_str()) + .map(|f| f.parse()) + .transpose()? + .unwrap_or_default(); + let new = format.from_reader(File::open(path)?)?; + config = merge_configs(config, new); + } + } + serde_json::from_value(Value::Object(config)).with_kind(crate::ErrorKind::Deserialization) +} + +pub fn merge_configs(mut first: Config, second: Config) -> Config { + for (k, v) in second.into_iter() { + let new = match first.remove(&k) { + None => v, + Some(old) => match (old, v) { + (Value::Object(first), Value::Object(second)) => { + Value::Object(merge_configs(first, second)) + } + (first, _) => first, + }, + }; + first.insert(k, new); + } + first +} diff --git a/backend/src/util/mod.rs b/backend/src/util/mod.rs index c3fcb7befc..0845231426 100644 --- a/backend/src/util/mod.rs +++ b/backend/src/util/mod.rs @@ -10,22 +10,21 @@ use std::task::{Context, Poll}; use async_trait::async_trait; use clap::ArgMatches; use color_eyre::eyre::{self, eyre}; -use digest::Digest; use fd_lock_rs::FdLock; use futures::future::BoxFuture; use futures::FutureExt; +pub use helpers::NonDetachingJoinHandle; use lazy_static::lazy_static; +pub use models::Version; use pin_project::pin_project; +use sha2_old::Digest; use tokio::fs::File; use tokio::sync::{Mutex, OwnedMutexGuard, RwLock}; use tracing::instrument; use crate::shutdown::Shutdown; use crate::{Error, ResultExt as _}; - - -pub use helpers::NonDetachingJoinHandle; -pub use models::Version; +pub mod config; pub mod io; pub mod logger; pub mod serde; @@ -251,7 +250,6 @@ where } } - pub struct GeneralGuard T, T = ()>(Option); impl T, T> GeneralGuard { pub fn new(f: F) -> Self {