aboutsummaryrefslogtreecommitdiffstats
path: root/src/swarm/auth.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/swarm/auth.rs')
-rw-r--r--src/swarm/auth.rs53
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]