mod filter_specs;use crate::to_wide;use anyhow::Result;use std::ffi::OsStr;use std::mem::zeroed;use std::ptr::null;use std::ptr::null_mut;use windows_sys::Win32::Foundation::FWP_E_ALREADY_EXISTS;use windows_sys::Win32::Foundation::FWP_E_FILTER_NOT_FOUND;use windows_sys::Win32::Foundation::FWP_E_NOT_FOUND;use windows_sys::Win32::Foundation::HANDLE;use windows_sys::Win32::Foundation::HLOCAL;use windows_sys::Win32::Foundation::LocalFree;use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FWP_ACTION_BLOCK;use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FWP_ACTRL_MATCH_FILTER;use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FWP_BYTE_BLOB;use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FWP_CONDITION_VALUE0;use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FWP_CONDITION_VALUE0_0;use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FWP_EMPTY;use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FWP_MATCH_EQUAL;use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FWP_SECURITY_DESCRIPTOR_TYPE;use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FWP_UINT8;use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FWP_UINT16;use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FWP_VALUE0;use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FWPM_ACTION0;use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FWPM_ACTION0_0;use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FWPM_CONDITION_ALE_USER_ID;use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FWPM_CONDITION_IP_PROTOCOL;use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FWPM_CONDITION_IP_REMOTE_PORT;use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FWPM_DISPLAY_DATA0;use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FWPM_FILTER_CONDITION0;use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FWPM_FILTER_FLAG_PERSISTENT;use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FWPM_FILTER0;use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FWPM_FILTER0_0;use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FWPM_PROVIDER_FLAG_PERSISTENT;use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FWPM_PROVIDER0;use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FWPM_SESSION0;use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FWPM_SUBLAYER_FLAG_PERSISTENT;use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FWPM_SUBLAYER0;use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FwpmEngineClose0;use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FwpmEngineOpen0;use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FwpmFilterAdd0;use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FwpmFilterDeleteByKey0;use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FwpmProviderAdd0;use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FwpmSubLayerAdd0;use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FwpmTransactionAbort0;use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FwpmTransactionBegin0;use windows_sys::Win32::NetworkManagement::WindowsFilteringPlatform::FwpmTransactionCommit0;use windows_sys::Win32::Security::Authorization::BuildExplicitAccessWithNameW;use windows_sys::Win32::Security::Authorization::BuildSecurityDescriptorW;use windows_sys::Win32::Security::Authorization::EXPLICIT_ACCESS_W;use windows_sys::Win32::Security::Authorization::GRANT_ACCESS;use windows_sys::Win32::Security::PSECURITY_DESCRIPTOR;use windows_sys::Win32::System::Rpc::RPC_C_AUTHN_DEFAULT;use windows_sys::Win32::System::Threading::INFINITE;use windows_sys::core::GUID;use filter_specs::ConditionSpec;use filter_specs::FILTER_SPECS;use filter_specs::FilterSpec;const SESSION_NAME: &str = "Codex Windows Sandbox WFP";const PROVIDER_NAME: &str = "Codex Windows Sandbox WFP";const PROVIDER_DESCRIPTION: &str = "Persistent WFP provider for Codex Windows sandbox filters";const SUBLAYER_NAME: &str = "Codex Windows Sandbox WFP";const SUBLAYER_DESCRIPTION: &str = "Persistent WFP sublayer for Codex Windows sandbox filters";// WFP identifies persistent providers, sublayers, and filters by stable GUIDs.// These values are Codex-owned identities; do not regenerate them unless we// intentionally want to orphan old objects and create a new WFP namespace.const PROVIDER_KEY: GUID = GUID::from_u128(0x2e31d31c_3948_4753_9117_e5d1a6496f41);const SUBLAYER_KEY: GUID = GUID::from_u128(0xe65054fd_4d32_4c7c_95ef_621f0cf6431a);/// Installs the persistent Codex WFP filters for `account`.////// This is intended to run from the already-elevated setup helper. Callers/// should treat any returned error as non-fatal to the rest of setup.pub fn install_wfp_filters_for_account(account: &str) -> Result<usize> { let engine = Engine::open()?; let mut transaction = engine.begin_transaction()?; ensure_provider(engine.handle)?; ensure_sublayer(engine.handle)?; let user_condition = UserMatchCondition::for_account(account)?; let mut installed_filter_count = 0; for spec in FILTER_SPECS { delete_filter_if_present(engine.handle, &spec.key)?; add_filter(engine.handle, spec, &user_condition)?; installed_filter_count += 1; } transaction.commit()?; Ok(installed_filter_count)}/// Owns an open WFP engine handle and closes it on drop.struct Engine { handle: HANDLE,}impl Engine { fn open() -> Result<Self> { let session_name = to_wide(OsStr::new(SESSION_NAME)); let mut session: FWPM_SESSION0 = unsafe { zeroed() }; session.displayData = FWPM_DISPLAY_DATA0 { name: session_name.as_ptr() as *mut _, description: null_mut(), }; session.txnWaitTimeoutInMSec = INFINITE; let mut handle = HANDLE::default(); let result = unsafe { FwpmEngineOpen0( null(), RPC_C_AUTHN_DEFAULT as u32, null(), &session, &mut handle, ) }; ensure_success(result, "FwpmEngineOpen0")?; Ok(Self { handle }) } fn begin_transaction(&self) -> Result<Transaction<'_>> { let result = unsafe { FwpmTransactionBegin0(self.handle, 0) }; ensure_success(result, "FwpmTransactionBegin0")?; Ok(Transaction { engine: self, committed: false, }) }}impl Drop for Engine { fn drop(&mut self) { unsafe { FwpmEngineClose0(self.handle); } }}/// Aborts an open WFP transaction unless it was explicitly committed.struct Transaction<'a> { engine: &'a Engine, committed: bool,}impl Transaction<'_> { fn commit(&mut self) -> Result<()> { let result = unsafe { FwpmTransactionCommit0(self.engine.handle) }; ensure_success(result, "FwpmTransactionCommit0")?; self.committed = true; Ok(()) }}impl Drop for Transaction<'_> { fn drop(&mut self) { if !self.committed { unsafe { FwpmTransactionAbort0(self.engine.handle); } } }}/// Builds the ALE_USER_ID condition blob that scopes filters to one account.struct UserMatchCondition { security_descriptor: PSECURITY_DESCRIPTOR, blob: FWP_BYTE_BLOB,}impl UserMatchCondition { fn for_account(account: &str) -> Result<Self> { let account_w = to_wide(OsStr::new(account)); let mut access: EXPLICIT_ACCESS_W = unsafe { zeroed() }; unsafe { BuildExplicitAccessWithNameW( &mut access, account_w.as_ptr(), FWP_ACTRL_MATCH_FILTER, GRANT_ACCESS, 0, ); } let mut security_descriptor: PSECURITY_DESCRIPTOR = null_mut(); let mut security_descriptor_len = 0; let result = unsafe { BuildSecurityDescriptorW( null(), null(), 1, &access, 0, null(), null_mut(), &mut security_descriptor_len, &mut security_descriptor, ) }; ensure_success(result, "BuildSecurityDescriptorW")?; Ok(Self { security_descriptor, blob: FWP_BYTE_BLOB { size: security_descriptor_len, data: security_descriptor as *mut u8, }, }) }}impl Drop for UserMatchCondition { fn drop(&mut self) { if !self.security_descriptor.is_null() { unsafe { LocalFree(self.security_descriptor as HLOCAL); } } }}/// Ensures the persistent Codex WFP provider exists.fn ensure_provider(engine: HANDLE) -> Result<()> { let provider_name = to_wide(OsStr::new(PROVIDER_NAME)); let provider_description = to_wide(OsStr::new(PROVIDER_DESCRIPTION)); let provider = FWPM_PROVIDER0 { providerKey: PROVIDER_KEY, displayData: FWPM_DISPLAY_DATA0 { name: provider_name.as_ptr() as *mut _, description: provider_description.as_ptr() as *mut _, }, flags: FWPM_PROVIDER_FLAG_PERSISTENT, providerData: empty_blob(), serviceName: null_mut(), }; let result = unsafe { FwpmProviderAdd0(engine, &provider, null_mut()) }; ensure_success_or(result, "FwpmProviderAdd0", &[FWP_E_ALREADY_EXISTS as u32])}/// Ensures the persistent Codex sublayer exists under the Codex provider.fn ensure_sublayer(engine: HANDLE) -> Result<()> { let sublayer_name = to_wide(OsStr::new(SUBLAYER_NAME)); let sublayer_description = to_wide(OsStr::new(SUBLAYER_DESCRIPTION)); let provider_key = PROVIDER_KEY; let sublayer = FWPM_SUBLAYER0 { subLayerKey: SUBLAYER_KEY, displayData: FWPM_DISPLAY_DATA0 { name: sublayer_name.as_ptr() as *mut _, description: sublayer_description.as_ptr() as *mut _, }, flags: FWPM_SUBLAYER_FLAG_PERSISTENT, providerKey: &provider_key as *const _ as *mut _, providerData: empty_blob(), weight: 0x8000, }; let result = unsafe { FwpmSubLayerAdd0(engine, &sublayer, null_mut()) }; ensure_success_or(result, "FwpmSubLayerAdd0", &[FWP_E_ALREADY_EXISTS as u32])}/// Adds one blocking WFP filter from the static filter spec list.fn add_filter( engine: HANDLE, spec: &FilterSpec, user_condition: &UserMatchCondition,) -> Result<()> { let filter_name = to_wide(OsStr::new(spec.name)); let filter_description = to_wide(OsStr::new(spec.description)); let mut filter_conditions = build_conditions(spec.conditions, user_condition); let provider_key = PROVIDER_KEY; let filter = FWPM_FILTER0 { filterKey: spec.key, displayData: FWPM_DISPLAY_DATA0 { name: filter_name.as_ptr() as *mut _, description: filter_description.as_ptr() as *mut _, }, flags: FWPM_FILTER_FLAG_PERSISTENT, providerKey: &provider_key as *const _ as *mut _, providerData: empty_blob(), layerKey: spec.layer_key, subLayerKey: SUBLAYER_KEY, weight: empty_value(), numFilterConditions: filter_conditions.len() as u32, filterCondition: filter_conditions.as_mut_ptr(), action: FWPM_ACTION0 { r#type: FWP_ACTION_BLOCK, Anonymous: FWPM_ACTION0_0 { filterType: zero_guid(), }, }, Anonymous: FWPM_FILTER0_0 { rawContext: 0 }, reserved: null_mut(), filterId: 0, effectiveWeight: empty_value(), }; let mut filter_id = 0_u64; let result = unsafe { FwpmFilterAdd0(engine, &filter, null_mut(), &mut filter_id) }; ensure_success(result, &format!("FwpmFilterAdd0({})", spec.name))}/// Converts our compact condition specs into WFP filter conditions.fn build_conditions( specs: &[ConditionSpec], user_condition: &UserMatchCondition,) -> Vec<FWPM_FILTER_CONDITION0> { specs .iter() .map(|spec| match spec { ConditionSpec::User => FWPM_FILTER_CONDITION0 { fieldKey: FWPM_CONDITION_ALE_USER_ID, matchType: FWP_MATCH_EQUAL, conditionValue: FWP_CONDITION_VALUE0 { r#type: FWP_SECURITY_DESCRIPTOR_TYPE, Anonymous: FWP_CONDITION_VALUE0_0 { sd: &user_condition.blob as *const _ as *mut _, }, }, }, ConditionSpec::Protocol(protocol) => FWPM_FILTER_CONDITION0 { fieldKey: FWPM_CONDITION_IP_PROTOCOL, matchType: FWP_MATCH_EQUAL, conditionValue: FWP_CONDITION_VALUE0 { r#type: FWP_UINT8, Anonymous: FWP_CONDITION_VALUE0_0 { uint8: *protocol }, }, }, ConditionSpec::RemotePort(port) => FWPM_FILTER_CONDITION0 { fieldKey: FWPM_CONDITION_IP_REMOTE_PORT, matchType: FWP_MATCH_EQUAL, conditionValue: FWP_CONDITION_VALUE0 { r#type: FWP_UINT16, Anonymous: FWP_CONDITION_VALUE0_0 { uint16: *port }, }, }, }) .collect()}/// Deletes an old copy of a filter before re-adding it.fn delete_filter_if_present(engine: HANDLE, key: &GUID) -> Result<()> { let result = unsafe { FwpmFilterDeleteByKey0(engine, key) }; ensure_success_or( result, "FwpmFilterDeleteByKey0", &[FWP_E_FILTER_NOT_FOUND as u32, FWP_E_NOT_FOUND as u32], )}fn ensure_success(result: u32, operation: &str) -> Result<()> { ensure_success_or(result, operation, &[])}fn ensure_success_or(result: u32, operation: &str, allowed: &[u32]) -> Result<()> { if result == 0 || allowed.contains(&result) { Ok(()) } else { Err(anyhow::anyhow!( "{operation} failed: {}", format_error_code(result) )) }}fn format_error_code(result: u32) -> String { format!("0x{result:08X}")}fn empty_blob() -> FWP_BYTE_BLOB { FWP_BYTE_BLOB { size: 0, data: null_mut(), }}fn empty_value() -> FWP_VALUE0 { FWP_VALUE0 { r#type: FWP_EMPTY, Anonymous: unsafe { zeroed() }, }}fn zero_guid() -> GUID { GUID::from_u128(0)}#[cfg(test)]mod tests { use super::FILTER_SPECS; use pretty_assertions::assert_eq; use std::collections::BTreeSet; #[test] fn filter_keys_are_unique() { let keys = FILTER_SPECS .iter() .map(|spec| { ( spec.key.data1, spec.key.data2, spec.key.data3, spec.key.data4, ) }) .collect::<BTreeSet<_>>(); assert_eq!(keys.len(), FILTER_SPECS.len()); } #[test] fn filter_names_are_unique() { let names = FILTER_SPECS .iter() .map(|spec| spec.name) .collect::<BTreeSet<_>>(); assert_eq!(names.len(), FILTER_SPECS.len()); }}