diff options
Diffstat (limited to 'src/swarm/auth.rs')
| -rw-r--r-- | src/swarm/auth.rs | 53 |
1 files changed, 26 insertions, 27 deletions
diff --git a/src/swarm/auth.rs b/src/swarm/auth.rs index 088f615..98a004c 100644 --- a/src/swarm/auth.rs +++ b/src/swarm/auth.rs @@ -21,7 +21,7 @@ use std::sync::Mutex; use std::time::{Duration, Instant}; use crate::locks::MutexExt; -use anyhow::{Context, Result, bail}; +use anyhow::{Result, bail}; use sha2::{Digest, Sha256}; const HELLO_LABEL: &[u8] = b"continuum/hello/1"; @@ -40,37 +40,25 @@ struct Rejections { suppressed: u64, } -/// A key is a secret: a file others may read is worth a warning (not an error: a -/// group may be deliberate, e.g. shared with a deployment tool). `what`: which key. -pub(crate) fn warn_if_readable_by_others(path: &Path, what: &str) { - #[cfg(unix)] - { - use std::os::unix::fs::PermissionsExt; - if let Ok(metadata) = std::fs::metadata(path) { - let mode = metadata.permissions().mode(); - if mode & 0o077 != 0 { - tracing::warn!( - path = %path.display(), - mode = format!("{:o}", mode & 0o777), - "The {what} file is readable by others than its owner; chmod 600 it" - ); - } - } - } - #[cfg(not(unix))] - let _ = (path, what); -} - /// At most one rejection log line per this interval. const REJECTION_LOG_INTERVAL: Duration = Duration::from_secs(10); impl SwarmKey { /// Reads the key from a file; its bytes are the key, as they are. Generate one with /// e.g. `head -c 32 /dev/urandom > swarm.key`. - pub(crate) fn from_file(path: &Path) -> Result<Self> { - let key = std::fs::read(path) - .with_context(|| format!("Reading the swarm key from {}", path.display()))?; - warn_if_readable_by_others(path, "swarm key"); + /// With `create`, a new one (32 random bytes) if there is no file at `path`. + pub(crate) fn from_file(path: &Path, create: bool) -> Result<Self> { + let (key, created) = crate::files::key_file( + path, + "swarm key", + create, + "swarm-key-create", + "on the swarm's first node; the others need a copy of it", + 32, + )?; + if created { + tracing::info!(path = %path.display(), "Created a new swarm key: copy it to the swarm's other nodes"); + } if key.len() < 16 { bail!( "The swarm key in {} has {} bytes; use at least 16 (32 random bytes recommended)", @@ -172,7 +160,18 @@ mod tests { use super::*; fn hex(bytes: &[u8]) -> String { - bytes.iter().map(|byte| format!("{byte:02x}")).collect() + crate::transport::Hex(bytes).to_string() + } + + /// A swarm key file is made only when asked, then read as any other. + #[test] + fn swarm_key_created_only_when_asked() { + let path = crate::files::scratch_dir("swarm-key-create").join("swarm.key"); + assert!(SwarmKey::from_file(&path, false).is_err()); + assert!(!path.exists()); + let created = SwarmKey::from_file(&path, true).unwrap(); + assert_eq!(created.key.len(), 32); + assert_eq!(SwarmKey::from_file(&path, false).unwrap().key, created.key); } #[test] |
