Skip to content

Commit

Permalink
Sync all servers on new device enrollment (#427)
Browse files Browse the repository at this point in the history
* Expose load_servers() on NetworkAccount.

* Write out all origin servers in pairing enrollment.

* Make load_servers() private.

As the in-memory collection returned by servers() should always be in
sync with the state.

* Update to zxcvbn@3.0.1.

* Bump patch version.
  • Loading branch information
tmpfs authored May 25, 2024
1 parent 4d97fd4 commit b10620d
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 39 deletions.
19 changes: 10 additions & 9 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "sos"
version = "0.11.5"
version = "0.11.6"
edition = "2021"
rust-version = "1.75.0"
description = "Distributed, encrypted database for private secrets."
Expand Down Expand Up @@ -94,7 +94,7 @@ crossterm = "0.27"
ctrlc = "3"

[dependencies.sos-net]
version = "0.11.5"
version = "0.11.6"
features = ["full"]
path = "crates/net"

Expand Down
4 changes: 2 additions & 2 deletions crates/net/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "sos-net"
version = "0.11.5"
version = "0.11.6"
edition = "2021"
description = "Networking library for the Save Our Secrets SDK."
homepage = "https://saveoursecrets.com"
Expand Down Expand Up @@ -102,7 +102,7 @@ utoipa-rapidoc = { version = "3", features = ["axum"], optional = true }
snow = { version = "0.9", optional = true }

[dependencies.sos-sdk]
version = "0.11.3"
version = "0.11.6"
features = ["sync"]
path = "../sdk"

Expand Down
24 changes: 17 additions & 7 deletions crates/net/src/client/account/network_account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,11 +231,25 @@ impl NetworkAccount {
}

/// List the origin servers.
pub async fn servers(&self) -> Vec<Origin> {
///
/// Derived from the currently configuted in-memory remotes.
pub async fn servers(&self) -> HashSet<Origin> {
let remotes = self.remotes.read().await;
remotes.keys().cloned().collect()
}

/// Load origin servers from disc.
async fn load_servers(&self) -> Result<Option<HashSet<Origin>>> {
let remotes_file = self.paths().remote_origins();
if vfs::try_exists(&remotes_file).await? {
let contents = vfs::read(&remotes_file).await?;
let origins: HashSet<Origin> = serde_json::from_slice(&contents)?;
Ok(Some(origins))
} else {
Ok(None)
}
}

/// Inflight file transfers.
pub async fn inflight_transfers(&self) -> Result<Arc<InflightTransfers>> {
let storage = self.storage().await?;
Expand Down Expand Up @@ -644,17 +658,14 @@ impl Account for NetworkAccount {
folders
};

// Without an explicit connectio id use the inferred
// Without an explicit connection id use the inferred
// connection identifier
if self.connection_id.is_none() {
self.connection_id = self.client_connection_id().await.ok();
}

// Load origins from disc and create remote definitions
let remotes_file = self.paths().remote_origins();
if vfs::try_exists(&remotes_file).await? {
let contents = vfs::read(&remotes_file).await?;
let origins: HashSet<Origin> = serde_json::from_slice(&contents)?;
if let Some(origins) = self.load_servers().await? {
let mut remotes: Remotes = Default::default();

for origin in origins {
Expand All @@ -663,7 +674,6 @@ impl Account for NetworkAccount {
}

self.remotes = Arc::new(RwLock::new(remotes));

self.start_file_transfers().await?;
}

Expand Down
27 changes: 11 additions & 16 deletions crates/net/src/client/pairing/enrollment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ pub struct DeviceEnrollment {
device_vault: Vec<u8>,
/// Account name extracted from the account event logs.
account_name: Option<String>,
/// Collection of server origins.
servers: HashSet<Origin>,
}

impl DeviceEnrollment {
Expand All @@ -70,6 +72,7 @@ impl DeviceEnrollment {
origin: Origin,
device_signer: DeviceSigner,
device_vault: Vec<u8>,
servers: HashSet<Origin>,
data_dir: Option<PathBuf>,
) -> Result<Self> {
let address = account_signing_key.address()?;
Expand Down Expand Up @@ -98,6 +101,7 @@ impl DeviceEnrollment {
public_identity: None,
device_vault,
account_name: None,
servers,
})
}

Expand Down Expand Up @@ -145,9 +149,10 @@ impl DeviceEnrollment {
// Write the vault containing the device signing key
vfs::write(self.paths.device_file(), &self.device_vault).await?;

// Add the remote origin so it is loaded as
// a remote on the next sign in
self.add_origin().await?;
// Add origin servers early so that they will be registered
// as remotes when the enrollment is finished and the account
// is authenticated
self.add_origin_servers().await?;

Ok(())
}
Expand All @@ -171,20 +176,10 @@ impl DeviceEnrollment {
Ok(account)
}

/// Add a remote origin to the enrolled account paths.
async fn add_origin(&self) -> Result<()> {
/// Add the server origins to the enrolled account paths.
async fn add_origin_servers(&self) -> Result<()> {
let remotes_file = self.paths.remote_origins();
let mut origins = if vfs::try_exists(&remotes_file).await? {
let contents = vfs::read(&remotes_file).await?;
let origins: HashSet<Origin> = serde_json::from_slice(&contents)?;
origins
} else {
HashSet::new()
};

origins.insert(self.origin.clone());

let data = serde_json::to_vec_pretty(&origins)?;
let data = serde_json::to_vec_pretty(&self.servers)?;
vfs::write(remotes_file, data).await?;
Ok(())
}
Expand Down
5 changes: 4 additions & 1 deletion crates/net/src/client/pairing/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
//! Protocol for pairing devices.
use crate::sdk::device::DeviceMetaData;
use crate::sdk::{device::DeviceMetaData, sync::Origin};
use serde::{Deserialize, Serialize};
use serde_with::{base64::Base64, serde_as};
use std::collections::HashSet;

mod enrollment;
mod error;
Expand Down Expand Up @@ -46,4 +47,6 @@ pub(super) struct PairingConfirmation(
/// Encoded device vault.
#[serde_as(as = "Base64")]
Vec<u8>,
/// List of origin servers.
HashSet<Origin>,
);
4 changes: 4 additions & 0 deletions crates/net/src/client/pairing/websocket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@ impl<'a> OfferPairing<'a> {
self.account.new_device_vault().await?;
let device_key_buffer =
manager.into_vault_buffer().await?;
let servers = self.account.servers().await;

self.register_device(device_signer.public_key(), device)
.await?;
Expand All @@ -369,6 +370,7 @@ impl<'a> OfferPairing<'a> {
account_signing_key,
device_signer.to_bytes(),
device_key_buffer,
servers,
));

let payload = if let Some(Tunnel::Transport(transport)) =
Expand Down Expand Up @@ -771,6 +773,7 @@ impl<'a> AcceptPairing<'a> {
signing_key,
device_signing_key_buf,
device_vault_buffer,
servers,
) = confirmation;
let signer: SingleParty = signing_key.try_into()?;
let server = self.share_url.server().clone();
Expand All @@ -781,6 +784,7 @@ impl<'a> AcceptPairing<'a> {
origin,
device_signing_key_buf.try_into()?,
device_vault_buffer,
servers,
data_dir,
)
.await?;
Expand Down
4 changes: 2 additions & 2 deletions crates/sdk/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "sos-sdk"
version = "0.11.5"
version = "0.11.6"
edition = "2021"
description = "Distributed, encrypted database for private secrets."
homepage = "https://saveoursecrets.com"
Expand Down Expand Up @@ -74,7 +74,7 @@ balloon-hash = { version = "0.4", features = ["std"]}
app_dirs2 = "2"
pem = { version = "3", features = ["serde"] }
tempfile = "3.5"
zxcvbn = { version = "3", git = "https://github.com/tmpfs/zxcvbn-rs", rev = "71d46b4d7ec05f97207c2e976efe19c9f9b1e62b", features = ["ser"]}
zxcvbn = { version = "3.0.1", features = ["ser"] }
totp-rs = { version = "5.5", features = ["qr", "serde_support", "zeroize"] }
vcard4 = { version = "0.5", features = ["serde"] }
async-once-cell = "0.5"
Expand Down

0 comments on commit b10620d

Please sign in to comment.