use super::{FRESH, written};
use crate::channel::material::{self, ADDRESS, ANCHORS, CHAIN, KEY};
use crate::channel::rendezvous::{self, PUBLIC, SALT};
use crate::reply::enrolled::{Enrolled, Handoff};
use crate::test_support::Scratch;
fn minted() -> Enrolled {
Enrolled {
grade: "foot".to_owned(),
name: "box-1".to_owned(),
address: "engine.invalid:7737".to_owned(),
ca: "-----BEGIN CERTIFICATE-----\nnotreal-ca\n-----END CERTIFICATE-----\n".to_owned(),
cert: "-----BEGIN CERTIFICATE-----\nnotreal-leaf\n-----END CERTIFICATE-----\n".to_owned(),
key: "-----BEGIN notreal KEY-----\nnotreal-key\n-----END notreal KEY-----\n".to_owned(),
rendezvous: None,
}
}
#[test]
fn the_four_files_are_the_entry_this_seat_itself_reads() {
let scratch = Scratch::new();
let dir = scratch.path().join("carry");
let said = written(&dir, &minted()).expect("the entry was filed");
assert!(said.contains(&dir.display().to_string()), "{said}");
let held = material::read_dir(&dir, material::Whose::Elsewhere)
.expect("it reads")
.expect("it holds a channel");
assert_eq!(held.address, "engine.invalid:7737");
assert_eq!(held.anchors, dir.join(ANCHORS));
assert_eq!(held.chain, dir.join(CHAIN));
assert_eq!(held.key, dir.join(KEY));
let material = minted();
for (leaf, body) in [
(ANCHORS, material.ca),
(CHAIN, material.cert),
(KEY, material.key),
] {
assert_eq!(
std::fs::read_to_string(dir.join(leaf)).expect(leaf),
body,
"{leaf}"
);
}
assert_eq!(
std::fs::read_to_string(dir.join(ADDRESS)).expect(ADDRESS),
"engine.invalid:7737\n"
);
}
#[cfg(unix)]
#[test]
fn the_files_are_created_readable_by_nobody_else() {
use std::os::unix::fs::PermissionsExt;
let scratch = Scratch::new();
let dir = scratch.path().join("carry");
written(&dir, &minted()).expect("the entry was filed");
for leaf in [ANCHORS, CHAIN, KEY, ADDRESS] {
let mode = std::fs::metadata(dir.join(leaf))
.expect(leaf)
.permissions()
.mode();
assert_eq!(mode & 0o077, 0, "{leaf} is readable off this account");
}
}
#[test]
fn a_directory_that_already_holds_material_refuses_and_names_the_remedy() {
let scratch = Scratch::new();
let dir = scratch.path().join("carry");
written(&dir, &minted()).expect("the first one was filed");
let refused = written(&dir, &minted()).expect_err("the second was refused");
assert!(refused.contains(ANCHORS), "{refused}");
assert!(refused.contains(FRESH), "{refused}");
assert_eq!(
std::fs::read_to_string(dir.join(ANCHORS)).expect(ANCHORS),
minted().ca
);
}
#[test]
fn a_destination_that_is_not_a_directory_says_so() {
let scratch = Scratch::new();
let blocked = scratch.path().join("occupied");
std::fs::write(&blocked, "notreal").expect("the blocker was written");
let refused = written(&blocked.join("under"), &minted()).expect_err("it was refused");
assert!(refused.contains("under"), "{refused}");
}
fn roving() -> Enrolled {
Enrolled {
rendezvous: Some(Handoff {
public: "ab".repeat(32),
salt: "cd".repeat(32),
}),
..minted()
}
}
fn names(dir: &std::path::Path) -> Vec<String> {
let mut found: Vec<String> = std::fs::read_dir(dir)
.expect("the entry")
.flatten()
.map(|entry| entry.file_name().to_string_lossy().into_owned())
.collect();
found.sort();
found
}
#[test]
fn the_pair_lands_as_the_two_files_the_rendezvous_reader_reads() {
let scratch = Scratch::new();
let plain = scratch.path().join("plain");
written(&plain, &minted()).expect("filed");
assert_eq!(names(&plain), [ADDRESS, ANCHORS, KEY, CHAIN]);
assert_eq!(rendezvous::read_dir(&plain), Ok(None));
let dir = scratch.path().join("roving");
let said = written(&dir, &roving()).expect("filed");
assert_eq!(names(&dir), [ADDRESS, ANCHORS, KEY, CHAIN, SALT, PUBLIC]);
for named in [PUBLIC, SALT] {
assert!(said.contains(named), "{named} unsaid: {said}");
}
let pairing = rendezvous::read_dir(&dir)
.expect("it reads")
.expect("it holds a pairing");
assert_eq!(pairing.engine, [0xab; 32]);
assert_eq!(pairing.salt, [0xcd; 32]);
assert_eq!(
std::fs::read_to_string(dir.join(PUBLIC)).expect(PUBLIC),
format!("{}\n", "ab".repeat(32))
);
}
#[cfg(unix)]
#[test]
fn the_public_key_is_open_and_the_salt_is_narrow() {
use std::os::unix::fs::PermissionsExt;
let scratch = Scratch::new();
let dir = scratch.path().join("roving");
written(&dir, &roving()).expect("filed");
let mode = |leaf: &str| {
std::fs::metadata(dir.join(leaf))
.expect(leaf)
.permissions()
.mode()
};
assert_eq!(
mode(SALT) & 0o077,
0,
"the salt is readable off this account"
);
assert_eq!(
mode(PUBLIC) & 0o022,
0,
"the public key is writable by others"
);
assert_eq!(mode(PUBLIC) & 0o400, 0o400, "the public key is unreadable");
}