diff --git a/Cargo.lock b/Cargo.lock index 69c4156..e46c786 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -389,6 +389,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + [[package]] name = "futf" version = "0.1.4" @@ -1109,6 +1115,19 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +dependencies = [ + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "rdrand", + "winapi", +] + [[package]] name = "rand" version = "0.7.3" @@ -1155,6 +1174,21 @@ dependencies = [ "rand_core 0.6.2", ] +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + [[package]] name = "rand_core" version = "0.5.1" @@ -1200,6 +1234,15 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +dependencies = [ + "rand_core 0.3.1", +] + [[package]] name = "redox_syscall" version = "0.2.5" @@ -1681,6 +1724,7 @@ dependencies = [ "standback", "stderrlog", "steamguard", + "tempdir", "termion", "text_io", "uuid", @@ -1746,6 +1790,16 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "tempdir" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" +dependencies = [ + "rand 0.4.6", + "remove_dir_all", +] + [[package]] name = "tempfile" version = "3.2.0" diff --git a/Cargo.toml b/Cargo.toml index 1f893f3..639b619 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,3 +34,6 @@ uuid = { version = "0.8", features = ["v4"] } termion = "1.5.6" steamguard = { path = "./steamguard" } dirs = "3.0.2" + +[dev-dependencies] +tempdir = "0.3" diff --git a/src/accountmanager.rs b/src/accountmanager.rs index f5b207c..5d62762 100644 --- a/src/accountmanager.rs +++ b/src/accountmanager.rs @@ -36,6 +36,7 @@ pub struct ManifestEntry { pub filename: String, #[serde(rename = "steamid")] pub steam_id: u64, + pub account_name: String, } impl Default for Manifest { @@ -81,6 +82,10 @@ impl Manifest { let file = File::open(path)?; let reader = BufReader::new(file); let account: SteamGuardAccount = serde_json::from_reader(reader)?; + ensure!( + account.account_name == entry.account_name, + "Account name in file does not match manifest entry." + ); self.accounts.push(Arc::new(Mutex::new(account))); } Ok(()) @@ -88,10 +93,11 @@ impl Manifest { pub fn add_account(&mut self, account: SteamGuardAccount) { debug!("adding account to manifest: {}", account.account_name); - let steamid = account.session.clone().unwrap().steam_id; + let steamid = account.session.as_ref().map_or(0, |s| s.steam_id); self.entries.push(ManifestEntry { filename: format!("{}.maFile", &account.account_name), steam_id: steamid, + account_name: account.account_name.clone(), encryption_iv: None, encryption_salt: None, }); @@ -147,3 +153,94 @@ impl Manifest { Ok(()) } } + +#[cfg(test)] +mod tests { + use super::*; + use tempdir::TempDir; + + #[test] + fn test_should_save_new_manifest() { + let tmp_dir = TempDir::new("steamguard-cli-test").unwrap(); + let manifest_path = tmp_dir.path().join("manifest.json"); + let manifest = Manifest::new(manifest_path.as_path()); + assert!(matches!(manifest.save(), Ok(_))); + } + + #[test] + fn test_should_save_and_load_manifest() { + let tmp_dir = TempDir::new("steamguard-cli-test").unwrap(); + let manifest_path = tmp_dir.path().join("manifest.json"); + let mut manifest = Manifest::new(manifest_path.as_path()); + let mut account = SteamGuardAccount::new(); + account.account_name = "asdf1234".into(); + account.revocation_code = "R12345".into(); + account.shared_secret = "secret".into(); + manifest.add_account(account); + assert!(matches!(manifest.save(), Ok(_))); + + let mut loaded_manifest = Manifest::load(manifest_path.as_path()).unwrap(); + assert_eq!(loaded_manifest.entries.len(), 1); + assert_eq!(loaded_manifest.entries[0].filename, "asdf1234.maFile"); + assert!(matches!(loaded_manifest.load_accounts(), Ok(_))); + assert_eq!( + loaded_manifest.entries.len(), + loaded_manifest.accounts.len() + ); + assert_eq!( + loaded_manifest.accounts[0].lock().unwrap().account_name, + "asdf1234" + ); + assert_eq!( + loaded_manifest.accounts[0].lock().unwrap().revocation_code, + "R12345" + ); + assert_eq!( + loaded_manifest.accounts[0].lock().unwrap().shared_secret, + "secret" + ); + } + + #[test] + fn test_should_import() { + let tmp_dir = TempDir::new("steamguard-cli-test").unwrap(); + let manifest_path = tmp_dir.path().join("manifest.json"); + let mut manifest = Manifest::new(manifest_path.as_path()); + let mut account = SteamGuardAccount::new(); + account.account_name = "asdf1234".into(); + account.revocation_code = "R12345".into(); + account.shared_secret = "secret".into(); + manifest.add_account(account); + assert!(matches!(manifest.save(), Ok(_))); + std::fs::remove_file(&manifest_path).unwrap(); + + let mut loaded_manifest = Manifest::new(manifest_path.as_path()); + assert!(matches!( + loaded_manifest.import_account( + tmp_dir + .path() + .join("asdf1234.maFile") + .into_os_string() + .into_string() + .unwrap() + ), + Ok(_) + )); + assert_eq!( + loaded_manifest.entries.len(), + loaded_manifest.accounts.len() + ); + assert_eq!( + loaded_manifest.accounts[0].lock().unwrap().account_name, + "asdf1234" + ); + assert_eq!( + loaded_manifest.accounts[0].lock().unwrap().revocation_code, + "R12345" + ); + assert_eq!( + loaded_manifest.accounts[0].lock().unwrap().shared_secret, + "secret" + ); + } +} diff --git a/steamguard/src/lib.rs b/steamguard/src/lib.rs index 9e5b0e9..ad42e40 100644 --- a/steamguard/src/lib.rs +++ b/steamguard/src/lib.rs @@ -50,7 +50,7 @@ pub struct SteamGuardAccount { pub fully_enrolled: bool, pub device_id: String, pub secret_1: String, - #[serde(rename = "Session")] + #[serde(default, rename = "Session")] pub session: Option, }