Watch
0
0
Fork
You've already forked hyperhive
0

render squid's users file from this hive's proxy credentials

This commit is contained in:
atlas 2026-10-28 13:02:25 +01:00 • committed by mara
commit 52d532ff5a

View file

@ -1,7 +1,8 @@
//! [`write_secret_0600`]: the one way hive-c0re puts a credential on disk.
//! [`write_secret_0600`] and [`write_secret_mode`]: the ways hive-c0re puts a
//! credential, or a hash of one, on disk.
use std::io::Write as _;
use std::os::unix::fs::OpenOptionsExt as _;
use std::os::unix::fs::{OpenOptionsExt as _, PermissionsExt as _};
use std::path::Path;
use anyhow::{Context as _, Result};
@ -13,6 +14,12 @@ use anyhow::{Context as _, Result};
/// reader (or a crash) never sees half of it. Errors carry paths, never
/// `contents`.
pub fn write_secret_0600(path: &Path, contents: &[u8]) -> Result<()> {
write_secret_mode(path, contents, 0o600)
}
/// [`write_secret_0600`] with the file's mode given, for a file another user
/// has to read (the group comes from the directory).
pub fn write_secret_mode(path: &Path, contents: &[u8], mode: u32) -> Result<()> {
if let Some(parent) = path.parent() {
std::fs::create_dir_all(parent).with_context(|| format!("create {}", parent.display()))?;
}
@ -27,9 +34,13 @@ pub fn write_secret_0600(path: &Path, contents: &[u8]) -> Result<()> {
let mut f = std::fs::OpenOptions::new()
.write(true)
.create_new(true)
.mode(0o600)
.mode(mode)
.open(&tmp)
.with_context(|| format!("create {}", tmp.display()))?;
// `open` masks the mode with the process umask; the mode is a property of
// the writer, not of the unit's umask.
f.set_permissions(std::fs::Permissions::from_mode(mode))
.with_context(|| format!("chmod {}", tmp.display()))?;
f.write_all(contents)
.and_then(|()| f.sync_all())
.with_context(|| format!("write {}", tmp.display()))?;
@ -38,7 +49,7 @@ pub fn write_secret_0600(path: &Path, contents: &[u8]) -> Result<()> {
#[cfg(test)]
mod tests {
use super::write_secret_0600;
use super::{write_secret_0600, write_secret_mode};
use std::os::unix::fs::PermissionsExt as _;
fn mode(path: &std::path::Path) -> u32 {
@ -76,4 +87,26 @@ mod tests {
write_secret_0600(&path, b"new\n").expect("writes");
assert_eq!(std::fs::read(&path).expect("read"), b"new\n");
}
/// A restrictive umask doesn't change the mode asked for. The umask is
/// process-wide, so the write happens in a child run of this test.
#[test]
fn the_mode_survives_a_restrictive_umask() {
const DIR: &str = "SECRET_FILE_UMASK_TEST_DIR";
if let Some(dir) = std::env::var_os(DIR) {
write_secret_mode(&std::path::Path::new(&dir).join("shared"), b"x\n", 0o640)
.expect("writes");
return;
}
let dir = tempfile::tempdir().expect("tempdir");
let status = std::process::Command::new("sh")
.arg("-c")
.arg(r#"umask 077 && exec "$0" --exact secret_file::tests::the_mode_survives_a_restrictive_umask"#)
.arg(std::env::current_exe().expect("test binary"))
.env(DIR, dir.path())
.status()
.expect("spawns the child");
assert!(status.success());
assert_eq!(mode(&dir.path().join("shared")), 0o640);
}
}