Move to rust stable, introduce mock for dbus in tests
This commit is contained in:
parent
37ef5d4e65
commit
96663abaef
9 changed files with 234 additions and 55 deletions
|
@ -6,20 +6,25 @@
|
|||
#![allow(non_snake_case)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
|
||||
include!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/constants.rs"));
|
||||
|
||||
use {
|
||||
anyhow::{anyhow, bail, ensure, Result},
|
||||
futures_util::TryStreamExt,
|
||||
libc::{freeaddrinfo, gai_strerror, getaddrinfo},
|
||||
nix::sys::socket::{SockaddrLike as _, SockaddrStorage},
|
||||
nix::unistd::Uid,
|
||||
std::collections::HashMap,
|
||||
std::env,
|
||||
std::ffi::{CStr, CString},
|
||||
std::net::{IpAddr, Ipv4Addr, Ipv6Addr},
|
||||
std::path::PathBuf,
|
||||
std::process::Command,
|
||||
std::str::FromStr,
|
||||
std::sync::Once,
|
||||
tokio::task,
|
||||
tokio::task::JoinHandle,
|
||||
};
|
||||
|
||||
pub type Eai = EaiRetcode;
|
||||
|
@ -106,3 +111,72 @@ pub fn resolve_system_and_us(hostname: &str) -> Result<(IpAddr, IpAddr)> {
|
|||
Ok((ip_from_system, ip_from_us))
|
||||
}
|
||||
}
|
||||
|
||||
pub type Restrictions = Vec<IpAddr>;
|
||||
|
||||
pub fn mock_dbus(responses: HashMap<Uid, Vec<Restrictions>>) -> JoinHandle<Result<()>> {
|
||||
async fn dbus_loop(mut responses: HashMap<Uid, Vec<Restrictions>>) -> Result<()> {
|
||||
use zbus::MessageType::*;
|
||||
|
||||
let mut responses_size: usize = responses.values().map(|v| v.len()).sum();
|
||||
for r in responses.values_mut() {
|
||||
r.reverse(); // we pop responses from the back, so...
|
||||
}
|
||||
|
||||
let connection = zbus::ConnectionBuilder::session()?.build().await?;
|
||||
let mut stream = zbus::MessageStream::from(&connection);
|
||||
while responses_size > 0 {
|
||||
let msg = stream
|
||||
.try_next()
|
||||
.await?
|
||||
.ok_or(anyhow!("Unparseable DBus message"))?;
|
||||
|
||||
if msg.header()?.message_type()? == MethodCall
|
||||
&& msg
|
||||
.interface()
|
||||
.ok_or(anyhow!("Invoked method has no interface"))?
|
||||
== DBUS_INTERFACE
|
||||
&& msg
|
||||
.member()
|
||||
.ok_or(anyhow!("Invoked method has no member"))?
|
||||
== DBUS_GET_RESTRICTIONS_METHOD
|
||||
{
|
||||
let user_id: u32 = msg.body()?;
|
||||
match responses.get_mut(&Uid::from(user_id)) {
|
||||
Some(answers) => match answers.pop() {
|
||||
Some(a) => {
|
||||
responses_size = responses_size - 1;
|
||||
let ips: Vec<String> = a.into_iter().map(|ip| ip.to_string()).collect();
|
||||
connection.reply(&msg, &ips).await
|
||||
}
|
||||
None => {
|
||||
connection
|
||||
.reply_error(
|
||||
&msg,
|
||||
"MockExhausted",
|
||||
&format!("DBus mock is saturated for user with id {}", user_id),
|
||||
)
|
||||
.await
|
||||
}
|
||||
},
|
||||
None => {
|
||||
connection
|
||||
.reply_error(
|
||||
&msg,
|
||||
"MockExhausted",
|
||||
&format!(
|
||||
"No mocked invocations available for user with id {}",
|
||||
user_id
|
||||
),
|
||||
)
|
||||
.await
|
||||
}
|
||||
}?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
task::spawn(async { dbus_loop(responses).await })
|
||||
}
|
||||
|
|
|
@ -7,10 +7,25 @@ use {
|
|||
crate::common::Eai,
|
||||
anyhow::Result,
|
||||
libc::{freeaddrinfo, gai_strerror, getaddrinfo},
|
||||
std::net::{IpAddr, Ipv4Addr},
|
||||
nix::unistd::getuid,
|
||||
once_cell::sync::Lazy,
|
||||
std::collections::HashMap,
|
||||
std::net::{IpAddr, Ipv4Addr, Ipv6Addr},
|
||||
std::time::Duration,
|
||||
tokio::time::timeout,
|
||||
};
|
||||
|
||||
static CLOUDFLARE_PARENTALCONTROL_ADDRS: Lazy<Vec<IpAddr>> = Lazy::new(|| {
|
||||
vec![
|
||||
IpAddr::V4(Ipv4Addr::new(1, 1, 1, 3)),
|
||||
IpAddr::V4(Ipv4Addr::new(1, 0, 0, 3)),
|
||||
IpAddr::V6(Ipv6Addr::new(2606, 4700, 4700, 0, 0, 0, 0, 1113)),
|
||||
IpAddr::V6(Ipv6Addr::new(2606, 4700, 4700, 0, 0, 0, 0, 1003)),
|
||||
]
|
||||
});
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn nss_module_is_loaded() -> Result<()> {
|
||||
common::setup()?;
|
||||
|
||||
|
@ -37,10 +52,15 @@ fn nss_module_is_loaded() -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn application_dns_is_nxdomain() -> Result<()> {
|
||||
common::setup()?;
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn application_dns_is_nxdomain() -> Result<()> {
|
||||
let dbus = common::mock_dbus(HashMap::from([(
|
||||
getuid(),
|
||||
vec![CLOUDFLARE_PARENTALCONTROL_ADDRS.clone()],
|
||||
)]));
|
||||
|
||||
common::setup()?;
|
||||
let hostname = std::ffi::CString::new("use-application-dns.net").unwrap();
|
||||
unsafe {
|
||||
let mut addr = std::ptr::null_mut();
|
||||
|
@ -60,32 +80,43 @@ fn application_dns_is_nxdomain() -> Result<()> {
|
|||
);
|
||||
freeaddrinfo(addr);
|
||||
};
|
||||
Ok(())
|
||||
|
||||
timeout(Duration::from_secs(1), dbus).await??
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn wikipedia_is_unrestricted() -> Result<()> {
|
||||
let dbus = common::mock_dbus(HashMap::from([(
|
||||
getuid(),
|
||||
vec![CLOUDFLARE_PARENTALCONTROL_ADDRS.clone()],
|
||||
)]));
|
||||
|
||||
fn wikipedia_is_unrestricted() -> Result<()> {
|
||||
let (system_addr, our_addr) = common::resolve_system_and_us("wikipedia.org")?;
|
||||
assert_eq!(system_addr, our_addr);
|
||||
Ok(())
|
||||
timeout(Duration::from_secs(1), dbus).await??
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
fn adultsite_is_restricted() -> Result<()> {
|
||||
async fn adultsite_is_restricted() -> Result<()> {
|
||||
let dbus = common::mock_dbus(HashMap::from([(
|
||||
getuid(),
|
||||
vec![CLOUDFLARE_PARENTALCONTROL_ADDRS.clone()],
|
||||
)]));
|
||||
|
||||
let (system_addr, our_addr) = common::resolve_system_and_us("pornhub.com")?;
|
||||
assert_ne!(system_addr, our_addr);
|
||||
assert_eq!(our_addr, IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)));
|
||||
Ok(())
|
||||
timeout(Duration::from_secs(1), dbus).await??
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
fn root_user_bypasses_restrictions() -> Result<()> {
|
||||
// TODO fake root
|
||||
async fn privileged_user_bypasses_restrictions() -> Result<()> {
|
||||
let dbus = common::mock_dbus(HashMap::from([(getuid(), vec![ /* no restriction */])]));
|
||||
|
||||
let (system_addr, our_addr) = common::resolve_system_and_us("pornhub.com")?;
|
||||
assert_eq!(system_addr, our_addr);
|
||||
Ok(())
|
||||
timeout(Duration::from_secs(1), dbus).await??
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue