From c52195dd8bd4b92133adfca9bbb402bbb64eb855 Mon Sep 17 00:00:00 2001 From: Matteo Settenvini Date: Wed, 24 Aug 2022 14:46:14 +0200 Subject: [PATCH] Add TLS support to resolver, implement DBus ifaces --- .gitignore | 5 +- Cargo.toml | 7 +- deny.toml | 8 +++ src/constants.rs | 13 ---- src/gethostbyname.rs | 4 +- src/lib.rs | 1 - src/policy_checker.rs | 102 -------------------------- src/policy_checker/dbus.rs | 26 +++++++ src/policy_checker/mod.rs | 111 +++++++++++++++++++++++++++++ tests/common/dbus.rs | 77 ++++++++++++++++++++ tests/{common.rs => common/mod.rs} | 76 ++++---------------- tests/integration_test.rs | 99 +++++++++++++++---------- 12 files changed, 308 insertions(+), 221 deletions(-) delete mode 100644 src/constants.rs delete mode 100644 src/policy_checker.rs create mode 100644 src/policy_checker/dbus.rs create mode 100644 src/policy_checker/mod.rs create mode 100644 tests/common/dbus.rs rename tests/{common.rs => common/mod.rs} (69%) diff --git a/.gitignore b/.gitignore index 619e22c..3f04c2d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,10 @@ # SPDX-FileCopyrightText: 2022 Matteo Settenvini # SPDX-License-Identifier: CC0-1.0 +*.orig +*~ + /build /target /Cargo.lock -/.gdb_history \ No newline at end of file +/.gdb_history diff --git a/Cargo.toml b/Cargo.toml index 9e6c62b..b5ad907 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,7 @@ name = "nss_malcontent" bindgen = "0.60" [dev-dependencies] +event-listener = "2.5" futures-util = "0.3" rusty-hook = "0.11" rusty-forkfork = "0.4" @@ -30,12 +31,14 @@ tokio = { version = "1", features = ["rt", "sync", "macros", "time"] } [dependencies] anyhow = "1.0" -const_format = "0.2" +gethostname = "0.2" libc = "0.2" once_cell = "1.13" log = "0.4" nix = { version = "0.24", features = ["socket", "user", "sched"] } +serde = "1.0" tokio = { version = "1", features = ["rt"] } -trust-dns-resolver = "0.21" +trust-dns-resolver = { version = "0.21", features = ["dns-over-rustls"] } trust-dns-proto = "0.21" zbus = { version = "3.0", default-features = false, features = ["tokio"] } +zvariant = "3.6" \ No newline at end of file diff --git a/deny.toml b/deny.toml index 5646371..2f47237 100644 --- a/deny.toml +++ b/deny.toml @@ -113,6 +113,7 @@ exceptions = [ # list #{ allow = ["Zlib"], name = "adler32", version = "*" }, { allow = ["Unicode-DFS-2016"], name = "unicode-ident", version = "*" }, + { allow = ["OpenSSL"], name = "ring", version = "*" }, ] # Some crates don't have (easily) machine readable licensing information, @@ -135,6 +136,13 @@ exceptions = [ #{ path = "LICENSE", hash = 0xbd0eed23 } #] +[[licenses.clarify]] +name = "ring" +expression = "MIT AND ISC AND OpenSSL" +license-files = [ + { path = "LICENSE", hash = 0xbd0eed23 }, +] + [licenses.private] # If true, ignores workspace crates that aren't published, or are only # published to private registries. diff --git a/src/constants.rs b/src/constants.rs deleted file mode 100644 index 6e35a9a..0000000 --- a/src/constants.rs +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Matteo Settenvini -// SPDX-License-Identifier: GPL-3.0-or-later - -use const_format::concatcp; - -#[allow(dead_code)] -const DBUS_INTERFACE: &str = "com.endlessm.ParentalControls.Dns"; - -#[allow(dead_code)] -const DBUS_OBJECT_PATH: &str = "com/endlessm/ParentalControls/Dns"; - -#[allow(dead_code)] -const DBUS_GET_RESTRICTIONS_METHOD: &str = concatcp!(DBUS_INTERFACE, ".", "GetRestrictions"); diff --git a/src/gethostbyname.rs b/src/gethostbyname.rs index 94584c7..578a76b 100644 --- a/src/gethostbyname.rs +++ b/src/gethostbyname.rs @@ -4,7 +4,7 @@ use { crate::helpers::{set_if_valid, write_record_name_to_buf, write_vector_to_buf}, crate::nss_bindings::{gaih_addrtuple, nss_status, HErrno}, - crate::policy_checker::{PolicyChecker as _, POLICY_CHECKER}, + crate::policy_checker::POLICY_CHECKER, libc::{c_char, c_int, hostent, size_t, AF_INET, AF_INET6}, nix::errno, nix::errno::Errno, @@ -46,7 +46,7 @@ pub async unsafe fn with(args: &mut Args) -> nss_status { set_if_valid(args.errnop, errno::from_i32(0)); set_if_valid(args.h_errnop, HErrno::Success); - match POLICY_CHECKER.resolver(None) { + match POLICY_CHECKER.resolver(None).await { Ok(None) => { // no restrictions for user, the next NSS module will decide nss_status::NSS_STATUS_NOTFOUND diff --git a/src/lib.rs b/src/lib.rs index 5c2893e..d077f95 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,7 +5,6 @@ #![allow(non_camel_case_types)] #![allow(non_snake_case)] -mod constants; mod gethostbyaddr; mod gethostbyname; mod helpers; diff --git a/src/policy_checker.rs b/src/policy_checker.rs deleted file mode 100644 index 352a504..0000000 --- a/src/policy_checker.rs +++ /dev/null @@ -1,102 +0,0 @@ -// SPDX-FileCopyrightText: 2022 Matteo Settenvini -// SPDX-License-Identifier: GPL-3.0-or-later - -use { - anyhow::Result, - nix::unistd::{getuid, Uid}, - once_cell::sync::Lazy, - std::collections::HashMap, - std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}, - std::sync::{Arc, RwLock}, - trust_dns_resolver::config as dns_config, - trust_dns_resolver::TokioAsyncResolver, -}; - -pub type Restrictions<'a> = &'a [IpAddr]; - -pub trait PolicyChecker { - fn resolver(&self, user: Option) -> Result>>; -} - -pub static POLICY_CHECKER: Lazy = - Lazy::new(|| MalcontentPolicyChecker::new()); - -static CLOUDFLARE_PARENTALCONTROL_ADDRS: Lazy> = 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)), - ] -}); - -// TODO: accept notifications about config changes -pub struct MalcontentPolicyChecker { - resolvers: RwLock>>>, -} - -impl MalcontentPolicyChecker { - pub fn new() -> Self { - Self { - resolvers: RwLock::new(HashMap::new()), - } - } - - fn restrictions<'a>(&'a self, user: Uid) -> Result>> { - if user.is_root() { - return Ok(None); - }; - - // TODO: for now, hardcoded DNS records, later go - // through D-Bus to malcontent and ask about user. - - Ok(Some(CLOUDFLARE_PARENTALCONTROL_ADDRS.as_slice())) - } -} - -impl PolicyChecker for MalcontentPolicyChecker { - fn resolver(&self, user: Option) -> Result>> { - let user = user.unwrap_or_else(|| getuid()); - { - let ro_resolvers = self.resolvers.read().unwrap(); - if let Some(resolver) = ro_resolvers.get(&user) { - return Ok(resolver.clone()); - } - } - - { - let mut rw_resolvers = self.resolvers.write().unwrap(); - if rw_resolvers.contains_key(&user) { - return self.resolver(Some(user)); - } - - let resolver = match self.restrictions(user)? { - Some(addrs) => { - let resolver_config = - addrs - .iter() - .fold(dns_config::ResolverConfig::new(), |mut config, addr| { - config.add_name_server(dns_config::NameServerConfig { - socket_addr: SocketAddr::new(*addr, 53), - protocol: dns_config::Protocol::Udp, - tls_dns_name: None, - trust_nx_responses: true, - bind_addr: None, - }); - config - }); - - let resolver = TokioAsyncResolver::tokio( - resolver_config, - dns_config::ResolverOpts::default(), - )?; - Some(Arc::new(resolver)) - } - None => None, - }; - rw_resolvers.insert(user, resolver); - } - - self.resolver(Some(user)) - } -} diff --git a/src/policy_checker/dbus.rs b/src/policy_checker/dbus.rs new file mode 100644 index 0000000..09ee099 --- /dev/null +++ b/src/policy_checker/dbus.rs @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: 2022 Matteo Settenvini +// SPDX-License-Identifier: GPL-3.0-or-later + +use { + serde::{Deserialize, Serialize}, + std::net::IpAddr, + zbus::{dbus_proxy, Result}, +}; + +#[dbus_proxy( + default_service = "com.endlessm.ParentalControls", + interface = "com.endlessm.ParentalControls.Dns", + default_path = "/com/endlessm/ParentalControls/Dns", + gen_blocking = false +)] +trait MalcontentDns { + fn get_restrictions(&self, uid: u32) -> Result; +} + +#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, zvariant::Type)] +pub struct Restriction { + pub ip: IpAddr, + pub hostname: String, +} + +pub type Restrictions = Vec; diff --git a/src/policy_checker/mod.rs b/src/policy_checker/mod.rs new file mode 100644 index 0000000..e33b94a --- /dev/null +++ b/src/policy_checker/mod.rs @@ -0,0 +1,111 @@ +// SPDX-FileCopyrightText: 2022 Matteo Settenvini +// SPDX-License-Identifier: GPL-3.0-or-later + +mod dbus; + +use { + self::dbus::*, + anyhow::Result, + nix::unistd::{getuid, Uid}, + once_cell::sync::Lazy, + std::collections::HashMap, + std::net::{SocketAddr, TcpStream}, + std::sync::{Arc, RwLock}, + trust_dns_proto::rr::domain::Name as DomainName, + trust_dns_resolver::config as dns_config, + trust_dns_resolver::TokioAsyncResolver, +}; + +pub use self::dbus::{Restriction, Restrictions}; + +const DNS_UDP_PORT: u16 = 53; +const DNS_TLS_PORT: u16 = 853; + +pub static POLICY_CHECKER: Lazy = Lazy::new(|| PolicyChecker::new()); + +// TODO: accept notifications about config changes +pub struct PolicyChecker { + resolvers: RwLock>>>, +} + +impl PolicyChecker { + pub fn new() -> Self { + Self { + resolvers: RwLock::new(HashMap::new()), + } + } + + async fn restrictions<'a>(&'a self, user: Uid) -> Result { + if user.is_root() { + return Ok(vec![]); + }; + + let connection = zbus::Connection::session().await?; + let proxy = MalcontentDnsProxy::new(&connection).await?; + Ok(proxy.get_restrictions(user.as_raw()).await?) + } + + pub async fn resolver(&self, user: Option) -> Result>> { + let user = user.unwrap_or_else(|| getuid()); + + // Check if already cached + { + let ro_resolvers = self.resolvers.read().unwrap(); + if let Some(resolver) = ro_resolvers.get(&user) { + return Ok(resolver.clone()); + } + } + + // Else, initialize and cache it + { + let mut rw_resolvers = self.resolvers.write().unwrap(); + if let Some(resolver) = rw_resolvers.get(&user) { + return Ok(resolver.clone()); + } + + // try first to prime resolver with DoT implementation, + // fallback to unencrypted only if not available. + let restrictions = self.restrictions(user).await?; + let resolver = if !restrictions.is_empty() { + let resolver = TokioAsyncResolver::tokio( + resolver_config_for(restrictions), + dns_config::ResolverOpts::default(), + )?; + Some(Arc::new(resolver)) + } else { + None + }; + + rw_resolvers.insert(user, resolver.clone()); + Ok(resolver) + } + } +} + +fn resolver_config_for(restrictions: Vec) -> dns_config::ResolverConfig { + use dns_config::NameServerConfigGroup as NsConfig; + + let resolver_config_group = + restrictions + .into_iter() + .fold(NsConfig::new(), |mut config, restr| { + let new_config = + if TcpStream::connect(SocketAddr::new(restr.ip, DNS_TLS_PORT)).is_ok() { + NsConfig::from_ips_tls(&[restr.ip], DNS_TLS_PORT, restr.hostname, true) + } else { + NsConfig::from_ips_clear(&[restr.ip], DNS_UDP_PORT, true) + }; + + config.merge(new_config); + config + }); + + let basename = gethostname::gethostname() + .as_os_str() + .to_str() + .map(|hn| DomainName::from_labels(hn.split('.')).ok()) + .flatten() + .map(|hn| hn.base_name()); + + dns_config::ResolverConfig::from_parts(basename, vec![], resolver_config_group) +} diff --git a/tests/common/dbus.rs b/tests/common/dbus.rs new file mode 100644 index 0000000..9a30c20 --- /dev/null +++ b/tests/common/dbus.rs @@ -0,0 +1,77 @@ +// SPDX-FileCopyrightText: 2022 Matteo Settenvini +// SPDX-License-Identifier: GPL-3.0-or-later + +include!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/src/policy_checker/dbus.rs" +)); + +use { + event_listener::{Event, EventListener}, + nix::unistd::Uid, + std::collections::HashMap, + zbus::dbus_interface, +}; + +pub struct MalcontentDBusMock { + responses: HashMap>, + invocations_left: usize, + finished: Event, +} + +#[dbus_interface(name = "com.endlessm.ParentalControls.Dns")] +impl MalcontentDBusMock { + fn get_restrictions(&mut self, user_id: u32) -> Restrictions { + let answers = self + .responses + .get_mut(&Uid::from_raw(user_id)) + .expect(&format!( + "MockError: No mocked invocations available for user with id {}", + user_id + )); + let restrictions = answers.pop().expect(&format!( + "MockError: DBus mock is saturated for user with id {}", + user_id + )); + self.invocations_left -= 1; + if self.invocations_left == 0 { + self.finished.notify(1); + } + restrictions + } +} + +impl MalcontentDBusMock { + pub fn new(mut responses: HashMap>) -> Self { + let 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 ret = Self { + responses, + invocations_left: responses_size, + finished: Event::new(), + }; + + if ret.invocations_left == 0 { + ret.finished.notify(1); + } + + ret + } + + pub fn waiter(&self) -> EventListener { + self.finished.listen() + } +} + +impl Drop for MalcontentDBusMock { + fn drop(&mut self) { + assert_eq!( + self.invocations_left, 0, + "MockError: During teardown, {} invocations are still left on the mock object", + self.invocations_left + ); + } +} diff --git a/tests/common.rs b/tests/common/mod.rs similarity index 69% rename from tests/common.rs rename to tests/common/mod.rs index e2b6a2b..856ad9e 100644 --- a/tests/common.rs +++ b/tests/common/mod.rs @@ -7,11 +7,12 @@ #![allow(dead_code)] include!(concat!(env!("OUT_DIR"), "/bindings.rs")); -include!(concat!(env!("CARGO_MANIFEST_DIR"), "/src/constants.rs")); + +mod dbus; use { + self::dbus::MalcontentDBusMock, anyhow::{anyhow, bail, ensure, Result}, - futures_util::TryStreamExt, libc::{freeaddrinfo, gai_strerror, getaddrinfo}, nix::sys::socket::{SockaddrLike as _, SockaddrStorage}, nix::unistd::Uid, @@ -27,6 +28,8 @@ use { tokio::task::JoinHandle, }; +pub use self::dbus::{Restriction, Restrictions}; + // Adapted from rusty_forkfork (which inherits it from rusty_fork) // to allow a custom pre-fork function #[macro_export] @@ -179,69 +182,16 @@ fn convert_addrinfo(sa: &SockaddrStorage) -> Result { } } -pub type Restrictions = Vec; - pub fn mock_dbus(responses: HashMap>) -> JoinHandle> { - async fn dbus_loop(mut responses: HashMap>) -> 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_raw(user_id)) { - Some(answers) => match answers.pop() { - Some(a) => { - responses_size = responses_size - 1; - let ips: Vec = 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 - } - }?; - } - } + async fn dbus_loop(responses: HashMap>) -> Result<()> { + let mock = MalcontentDBusMock::new(responses); + let waiter = mock.waiter(); + let _connection = zbus::ConnectionBuilder::session()? + .serve_at("/com/endlessm/ParentalControls/Dns", mock)? + .build() + .await?; + waiter.wait(); Ok(()) } diff --git a/tests/integration_test.rs b/tests/integration_test.rs index f8bda3b..45a303f 100644 --- a/tests/integration_test.rs +++ b/tests/integration_test.rs @@ -4,23 +4,35 @@ mod common; use { - crate::common::Eai, + crate::common::{Eai, Restriction, Restrictions}, anyhow::Result, libc::{freeaddrinfo, gai_strerror, getaddrinfo}, nix::unistd::getuid, once_cell::sync::Lazy, std::collections::HashMap, std::net::{IpAddr, Ipv4Addr, Ipv6Addr}, - //std::time::Duration, - //tokio::time::timeout, + std::time::Duration, + tokio::time::timeout, }; -static CLOUDFLARE_PARENTALCONTROL_ADDRS: Lazy> = Lazy::new(|| { +static CLOUDFLARE_PARENTALCONTROL_ADDRS: Lazy = 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)), + Restriction { + ip: IpAddr::V4(Ipv4Addr::new(1, 1, 1, 3)), + hostname: "cloudflare-dns.com".into(), + }, + Restriction { + ip: IpAddr::V4(Ipv4Addr::new(1, 0, 0, 3)), + hostname: "cloudflare-dns.com".into(), + }, + Restriction { + ip: IpAddr::V6(Ipv6Addr::new(2606, 4700, 4700, 0, 0, 0, 0, 1113)), + hostname: "cloudflare-dns.com".into(), + }, + Restriction { + ip: IpAddr::V6(Ipv6Addr::new(2606, 4700, 4700, 0, 0, 0, 0, 1003)), + hostname: "cloudflare-dns.com".into(), + }, ] }); @@ -36,7 +48,7 @@ fork_test! { fn application_dns_is_nxdomain() -> Result<()> { common::setup()?; tokio::runtime::Runtime::new().unwrap().block_on(async { - let _dbus = common::mock_dbus(HashMap::from([( + let dbus = common::mock_dbus(HashMap::from([( getuid(), vec![CLOUDFLARE_PARENTALCONTROL_ADDRS.clone()], )])); @@ -61,25 +73,26 @@ fork_test! { freeaddrinfo(addr); }; - //timeout(Duration::from_secs(1), dbus).await?? - Ok(()) + timeout(Duration::from_secs(1), dbus).await?? }) } #[test] fn getaddrinfo_resolution() -> Result<()> { common::setup()?; + + const HOSTNAME: &str = "gnome.org"; + tokio::runtime::Runtime::new().unwrap().block_on(async { - let _dbus = common::mock_dbus(HashMap::from([( + let dbus = common::mock_dbus(HashMap::from([( getuid(), vec![CLOUDFLARE_PARENTALCONTROL_ADDRS.clone()], )])); - let hostname = std::ffi::CString::new("gnome.org").unwrap(); unsafe { let mut addr = std::ptr::null_mut(); let getaddrinfo_status = getaddrinfo( - hostname.as_ptr(), + std::ffi::CString::new(HOSTNAME)?.as_ptr(), std::ptr::null(), std::ptr::null(), &mut addr, @@ -95,8 +108,7 @@ fork_test! { freeaddrinfo(addr); }; - //timeout(Duration::from_secs(1), dbus).await?? - Ok(()) + timeout(Duration::from_secs(1), dbus).await?? }) } @@ -105,48 +117,64 @@ fork_test! { fn wikipedia_is_unrestricted() -> Result<()> { common::setup()?; + const HOSTNAME: &str = "wikipedia.org"; + tokio::runtime::Runtime::new().unwrap().block_on(async { - let _dbus = common::mock_dbus(HashMap::from([( - getuid(), - vec![CLOUDFLARE_PARENTALCONTROL_ADDRS.clone()], - )])); - - const HOSTNAME: &str = "wikipedia.org"; - for family in [libc::AF_INET, libc::AF_INET6] { + let dbus = common::mock_dbus(HashMap::from([( + getuid(), + vec![CLOUDFLARE_PARENTALCONTROL_ADDRS.clone()], + )])); + let system_addr = common::resolve_with_system(family, HOSTNAME)?; let our_addr = common::resolve_with_module(family, HOSTNAME)?; assert_eq!(system_addr, our_addr); - } - //timeout(Duration::from_secs(1), dbus).await?? + timeout(Duration::from_secs(1), dbus).await???; + } Ok(()) }) } #[test] - fn adultsite_is_restricted() -> Result<()> { + fn adultsite_is_restricted_ipv4() -> Result<()> { common::setup()?; + const HOSTNAME: &str = "nudity.testcategory.com"; + tokio::runtime::Runtime::new().unwrap().block_on(async { - let _dbus = common::mock_dbus(HashMap::from([( + let dbus = common::mock_dbus(HashMap::from([( getuid(), vec![CLOUDFLARE_PARENTALCONTROL_ADDRS.clone()], )])); - const HOSTNAME: &str = "pornhub.com"; let system_addr = common::resolve_with_system(libc::AF_INET, HOSTNAME)?; let our_addr = common::resolve_with_module(libc::AF_INET, HOSTNAME)?; assert_ne!(system_addr, our_addr); assert_eq!(our_addr, IpAddr::V4(Ipv4Addr::UNSPECIFIED)); + timeout(Duration::from_secs(1), dbus).await?? + }) + } + + #[test] + fn adultsite_is_restricted_ipv6() -> Result<()> { + common::setup()?; + + const HOSTNAME: &str = "nudity.testcategory.com"; + + tokio::runtime::Runtime::new().unwrap().block_on(async { + let dbus = common::mock_dbus(HashMap::from([( + getuid(), + vec![CLOUDFLARE_PARENTALCONTROL_ADDRS.clone()], + )])); + let system_addr = common::resolve_with_system(libc::AF_INET6, HOSTNAME)?; let our_addr = common::resolve_with_module(libc::AF_INET6, HOSTNAME)?; assert_ne!(system_addr, our_addr); assert_eq!(our_addr, IpAddr::V6(Ipv6Addr::UNSPECIFIED)); - //timeout(Duration::from_secs(1), dbus).await?? - Ok(()) + timeout(Duration::from_secs(1), dbus).await?? }) } @@ -155,20 +183,17 @@ fork_test! { fn privileged_user_bypasses_restrictions() -> Result<()> { common::setup()?; + const HOSTNAME: &str = "nudity.testcategory.com"; + tokio::runtime::Runtime::new().unwrap().block_on(async { - let _dbus = common::mock_dbus(HashMap::from([(getuid(), vec![ /* no restriction */])])); - - const HOSTNAME: &str = "pornhub.com"; - for family in [libc::AF_INET, libc::AF_INET6] { + let dbus = common::mock_dbus(HashMap::from([(getuid(), vec![ /* no restriction */])])); let system_addr = common::resolve_with_system(family, HOSTNAME)?; let our_addr = common::resolve_with_module(family, HOSTNAME)?; assert_eq!(system_addr, our_addr); + timeout(Duration::from_secs(1), dbus).await??? } - - //timeout(Duration::from_secs(1), dbus).await?? Ok(()) }) } - }