use std::os::unix::{
fs::{PermissionsExt, symlink},
net::UnixListener,
};
use super::*;
#[tokio::test]
async fn bind_user_only_wide_directory_is_refused() {
let directory = tempfile::tempdir().unwrap();
fs::set_permissions(directory.path(), fs::Permissions::from_mode(0o755)).unwrap();
let location = SocketLocation::new(directory.path().join("ipc.sock"));
let result = bind_user_only(&location).await;
assert!(matches!(result, Err(SocketError::InsecureDirectory(_))));
assert!(!location.as_path().exists());
}
#[tokio::test]
async fn bind_user_only_private_directory_sets_socket_permissions() {
let directory = tempfile::tempdir().unwrap();
let location = SocketLocation::new(directory.path().join("private/ipc.sock"));
let listener = bind_user_only(&location).await.unwrap();
assert_eq!(
fs::symlink_metadata(location.as_path().parent().unwrap())
.unwrap()
.mode()
& PERMISSION_BITS,
DIRECTORY_MODE
);
assert_eq!(
Mode::from_raw_mode(rustix::fs::stat(location.as_path()).unwrap().st_mode).as_raw_mode(),
SOCKET_MODE
);
drop(listener);
}
#[tokio::test]
async fn bind_user_only_symlink_directory_is_refused() {
let directory = tempfile::tempdir().unwrap();
let target = directory.path().join("target");
fs::DirBuilder::new()
.mode(DIRECTORY_MODE)
.create(&target)
.unwrap();
let link = directory.path().join("link");
symlink(target, &link).unwrap();
let location = SocketLocation::new(link.join("ipc.sock"));
let result = bind_user_only(&location).await;
assert!(matches!(result, Err(SocketError::InsecureDirectory(_))));
}
#[tokio::test]
async fn bind_user_only_existing_non_socket_is_preserved() {
let directory = tempfile::tempdir().unwrap();
fs::set_permissions(directory.path(), fs::Permissions::from_mode(DIRECTORY_MODE)).unwrap();
let location = SocketLocation::new(directory.path().join("ipc.sock"));
fs::write(location.as_path(), b"keep").unwrap();
let result = bind_user_only(&location).await;
assert!(matches!(result, Err(SocketError::InsecureSocket(_))));
assert_eq!(fs::read(location.as_path()).unwrap(), b"keep");
}
#[tokio::test]
async fn connect_insecure_directory_is_refused_before_sending_secrets() {
let directory = tempfile::tempdir().unwrap();
fs::set_permissions(directory.path(), fs::Permissions::from_mode(0o755)).unwrap();
let location = SocketLocation::new(directory.path().join("ipc.sock"));
let _listener = UnixListener::bind(location.as_path()).unwrap();
let result = connect(&location).await;
assert!(matches!(result, Err(SocketError::InsecureDirectory(_))));
}