// SPDX-FileCopyrightText: 2022 Matteo Settenvini // SPDX-License-Identifier: GPL-3.0-or-later mod common; use { crate::common::Eai, 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, }; 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)), ] }); fork_test! { #[test] fn nss_module_is_loaded() -> Result<()> { common::setup()?; common::resolve_with_module(libc::AF_INET, "gnome.org")?; Ok(()) } #[test] fn application_dns_is_nxdomain() -> Result<()> { common::setup()?; tokio::runtime::Runtime::new().unwrap().block_on(async { let _dbus = common::mock_dbus(HashMap::from([( getuid(), vec![CLOUDFLARE_PARENTALCONTROL_ADDRS.clone()], )])); let hostname = std::ffi::CString::new("use-application-dns.net").unwrap(); unsafe { let mut addr = std::ptr::null_mut(); let getaddrinfo_status = getaddrinfo( hostname.as_ptr(), std::ptr::null(), std::ptr::null(), &mut addr, ); let error = std::ffi::CStr::from_ptr(gai_strerror(getaddrinfo_status)); assert_eq!( getaddrinfo_status, Eai::NoName.0, "Should have gotten no hostname (NXDOMAIN), instead got {}", error.to_str().unwrap() ); freeaddrinfo(addr); }; //timeout(Duration::from_secs(1), dbus).await?? Ok(()) }) } #[test] fn getaddrinfo_resolution() -> Result<()> { common::setup()?; tokio::runtime::Runtime::new().unwrap().block_on(async { 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::ptr::null(), std::ptr::null(), &mut addr, ); let error = std::ffi::CStr::from_ptr(gai_strerror(getaddrinfo_status)); assert_eq!( getaddrinfo_status, Eai::Success.0, "Should have gotten an hostname, instead got {}", error.to_str().unwrap() ); freeaddrinfo(addr); }; //timeout(Duration::from_secs(1), dbus).await?? Ok(()) }) } #[test] fn wikipedia_is_unrestricted() -> Result<()> { common::setup()?; 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 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?? Ok(()) }) } #[test] fn adultsite_is_restricted() -> Result<()> { common::setup()?; tokio::runtime::Runtime::new().unwrap().block_on(async { 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)); 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(()) }) } #[test] fn privileged_user_bypasses_restrictions() -> Result<()> { common::setup()?; 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 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?? Ok(()) }) } }