fix(mobile): detect and repair overriding Windows Firewall Block rules for pairing (#8846)
* fix(mobile): detect and repair overriding Windows Firewall Block rules for pairing Firewall inspection now reports an overriding inbound Block rule as blocked instead of false success, the UAC repair removes only conflicting rules for the current Orca executable, TCP pairing port, and Private profile before recreating the scoped allow rule, and the notice re-inspects Windows policy after repair instead of optimistically reporting success. Stale focus-triggered inspections can no longer overwrite a newer result during UAC elevation. Fixes #8371 * fix(mobile): inspect the ActiveStore so GPO firewall rules are visible Without -PolicyStore ActiveStore the NetSecurity queries read only the local persistent store, so a GPO-applied Block rule was invisible and the post-repair re-inspection could report a false success on managed hosts.
This commit is contained in:
parent
c13441123a
commit
9e2c63ec7c
|
|
@ -25,6 +25,7 @@ describe('windows mobile firewall', () => {
|
|||
const runPowerShell = vi.fn().mockResolvedValue(
|
||||
JSON.stringify({
|
||||
matchingRuleScopes: [{ remoteAddresses: ['192.168.0.0/24'] }],
|
||||
blockingRuleDetected: false,
|
||||
localAddress: '192.168.0.108',
|
||||
localPrefixLength: 24,
|
||||
privateFirewallEnabled: true,
|
||||
|
|
@ -38,22 +39,55 @@ describe('windows mobile firewall', () => {
|
|||
supported: true,
|
||||
port: 6768,
|
||||
ruleAllowed: true,
|
||||
blockingRuleDetected: false,
|
||||
privateFirewallEnabled: true,
|
||||
networkCategory: 'private',
|
||||
inspectionAvailable: true
|
||||
})
|
||||
|
||||
const script = runPowerShell.mock.calls[0]![0] as string
|
||||
// Why: without ActiveStore, GPO-applied Block rules are invisible and the
|
||||
// post-repair re-inspection could report a false success on managed hosts.
|
||||
expect(script).toContain(
|
||||
"Get-NetFirewallApplicationFilter -PolicyStore ActiveStore -Program 'C:\\Users\\O''Brien\\Orca\\Orca.exe'"
|
||||
)
|
||||
expect(script).toContain('Get-NetFirewallProfile -PolicyStore ActiveStore -Name Private')
|
||||
expect(script).toContain("LocalPort | Where-Object { [string]$_ -eq 'Any'")
|
||||
expect(script).toContain("[string]$_ -eq '6768'")
|
||||
expect(script).toContain("C:\\Users\\O''Brien\\Orca\\Orca.exe")
|
||||
expect(script).toContain("$profile -match 'Private'")
|
||||
expect(script).toContain("Get-NetIPAddress -IPAddress '192.168.0.108'")
|
||||
expect(script).toContain('Get-NetFirewallAddressFilter')
|
||||
expect(script).toContain("[string]$rule.Action -eq 'Block'")
|
||||
expect(script).toContain('remoteAddresses = @($addressFilter.RemoteAddress')
|
||||
expect(script).toContain('$localPrefixLength = [int]$ip.PrefixLength')
|
||||
})
|
||||
|
||||
it('treats an overlapping inbound Block rule as overriding a matching Allow rule', async () => {
|
||||
const runPowerShell = vi.fn().mockResolvedValue(
|
||||
JSON.stringify({
|
||||
matchingRuleScopes: [{ remoteAddresses: ['Any'] }],
|
||||
blockingRuleDetected: true,
|
||||
localAddress: '192.168.0.108',
|
||||
localPrefixLength: 24,
|
||||
privateFirewallEnabled: true,
|
||||
networkCategory: 'Private'
|
||||
})
|
||||
)
|
||||
|
||||
await expect(
|
||||
inspectWindowsMobileFirewall(6768, '192.168.0.108', environment(runPowerShell))
|
||||
).resolves.toEqual({
|
||||
supported: true,
|
||||
port: 6768,
|
||||
ruleAllowed: false,
|
||||
blockingRuleDetected: true,
|
||||
privateFirewallEnabled: true,
|
||||
networkCategory: 'private',
|
||||
inspectionAvailable: true
|
||||
})
|
||||
})
|
||||
|
||||
it('does not accept a qualifying rule whose remote-address scope excludes the phone subnet', async () => {
|
||||
const runPowerShell = vi.fn().mockResolvedValue(
|
||||
JSON.stringify({
|
||||
|
|
@ -100,6 +134,7 @@ describe('windows mobile firewall', () => {
|
|||
supported: true,
|
||||
port: 6768,
|
||||
ruleAllowed: false,
|
||||
blockingRuleDetected: false,
|
||||
privateFirewallEnabled: true,
|
||||
networkCategory: 'unknown',
|
||||
inspectionAvailable: false
|
||||
|
|
@ -133,6 +168,10 @@ describe('windows mobile firewall', () => {
|
|||
expect(encoded).toBeTruthy()
|
||||
const repairScript = Buffer.from(encoded!, 'base64').toString('utf16le')
|
||||
expect(repairScript).toContain("-Name 'Orca.MobilePairing'")
|
||||
expect(repairScript).toContain(
|
||||
"Where-Object { $_.Enabled -eq 'True' -and $_.Direction -eq 'Inbound' -and $_.Action -eq 'Block' }"
|
||||
)
|
||||
expect(repairScript).toContain('$rule | Remove-NetFirewallRule')
|
||||
expect(repairScript).toContain('-Profile Private')
|
||||
expect(repairScript).toContain('-Protocol TCP')
|
||||
expect(repairScript).toContain('-LocalPort 6769')
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ export type WindowsMobileFirewallEnvironment = {
|
|||
|
||||
type FirewallInspection = {
|
||||
matchingRuleScopes?: unknown
|
||||
blockingRuleDetected?: unknown
|
||||
localAddress?: unknown
|
||||
localPrefixLength?: unknown
|
||||
privateFirewallEnabled: boolean
|
||||
|
|
@ -51,14 +52,20 @@ export async function inspectWindowsMobileFirewall(
|
|||
POWERSHELL_TIMEOUT_MS
|
||||
)
|
||||
const result = JSON.parse(stdout.trim()) as FirewallInspection
|
||||
// Why: the phone address is unknown before pairing, so any matching Block
|
||||
// rule must fail this advisory check closed instead of risking false success.
|
||||
const blockingRuleDetected = result.blockingRuleDetected === true
|
||||
return {
|
||||
supported: true,
|
||||
port,
|
||||
ruleAllowed: hasSufficientWindowsFirewallRemoteScope(
|
||||
result.matchingRuleScopes,
|
||||
result.localAddress,
|
||||
result.localPrefixLength
|
||||
),
|
||||
ruleAllowed:
|
||||
!blockingRuleDetected &&
|
||||
hasSufficientWindowsFirewallRemoteScope(
|
||||
result.matchingRuleScopes,
|
||||
result.localAddress,
|
||||
result.localPrefixLength
|
||||
),
|
||||
blockingRuleDetected,
|
||||
privateFirewallEnabled: result.privateFirewallEnabled !== false,
|
||||
networkCategory: parseNetworkCategory(result.networkCategory),
|
||||
inspectionAvailable: true
|
||||
|
|
@ -131,6 +138,7 @@ function unavailableStatus(port: number): WindowsMobileFirewallStatus {
|
|||
supported: true,
|
||||
port,
|
||||
ruleAllowed: false,
|
||||
blockingRuleDetected: false,
|
||||
privateFirewallEnabled: true,
|
||||
networkCategory: 'unknown',
|
||||
inspectionAvailable: false
|
||||
|
|
@ -166,26 +174,34 @@ try {
|
|||
} catch {}`
|
||||
: ''
|
||||
// Why: NetSecurity filter properties are stable across localized Windows
|
||||
// display output and keep every rule's address scope independent.
|
||||
// display output and keep every rule's address scope independent. ActiveStore
|
||||
// includes GPO-applied rules the default persistent store hides, so managed
|
||||
// Block rules cannot produce a false success after repair.
|
||||
return `$ErrorActionPreference = 'Stop'
|
||||
$matchingRuleScopes = @()
|
||||
$rules = @(Get-NetFirewallApplicationFilter -Program ${quotePowerShell(executablePath)} -ErrorAction SilentlyContinue | Get-NetFirewallRule | Where-Object { $_.Enabled -eq 'True' -and $_.Direction -eq 'Inbound' -and $_.Action -eq 'Allow' })
|
||||
$blockingRuleDetected = $false
|
||||
$rules = @(Get-NetFirewallApplicationFilter -PolicyStore ActiveStore -Program ${quotePowerShell(executablePath)} -ErrorAction SilentlyContinue | Get-NetFirewallRule | Where-Object { $_.Enabled -eq 'True' -and $_.Direction -eq 'Inbound' })
|
||||
foreach ($rule in $rules) {
|
||||
$portFilter = $rule | Get-NetFirewallPortFilter
|
||||
$protocol = [string]$portFilter.Protocol
|
||||
$profile = [string]$rule.Profile
|
||||
$portMatches = @($portFilter.LocalPort | Where-Object { [string]$_ -eq 'Any' -or [string]$_ -eq '${port}' }).Count -gt 0
|
||||
if (($protocol -eq 'Any' -or $protocol -eq 'TCP' -or $protocol -eq '6') -and ($profile -eq 'Any' -or $profile -match 'Private') -and $portMatches) {
|
||||
$addressFilter = $rule | Get-NetFirewallAddressFilter
|
||||
$matchingRuleScopes += [pscustomobject]@{
|
||||
remoteAddresses = @($addressFilter.RemoteAddress | ForEach-Object { [string]$_ })
|
||||
if ([string]$rule.Action -eq 'Block') {
|
||||
$blockingRuleDetected = $true
|
||||
} elseif ([string]$rule.Action -eq 'Allow') {
|
||||
$addressFilter = $rule | Get-NetFirewallAddressFilter
|
||||
$matchingRuleScopes += [pscustomobject]@{
|
||||
remoteAddresses = @($addressFilter.RemoteAddress | ForEach-Object { [string]$_ })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$privateFirewallEnabled = [bool](Get-NetFirewallProfile -Name Private).Enabled
|
||||
$privateFirewallEnabled = [bool](Get-NetFirewallProfile -PolicyStore ActiveStore -Name Private).Enabled
|
||||
$networkCategory = 'Unknown'${addressLookup}
|
||||
[pscustomobject]@{
|
||||
matchingRuleScopes = @($matchingRuleScopes)
|
||||
blockingRuleDetected = $blockingRuleDetected
|
||||
localAddress = $localAddress
|
||||
localPrefixLength = $localPrefixLength
|
||||
privateFirewallEnabled = $privateFirewallEnabled
|
||||
|
|
@ -194,7 +210,21 @@ $networkCategory = 'Unknown'${addressLookup}
|
|||
}
|
||||
|
||||
function buildRepairScript(port: number, executablePath: string): string {
|
||||
// Why: Windows gives explicit Block rules precedence over narrower Allow
|
||||
// rules, so the user's repair action must remove exact-app conflicts first.
|
||||
// Removal deliberately ignores the Block rule's remote-address scope,
|
||||
// mirroring the fail-closed inspection (the phone address is unknown).
|
||||
return `$ErrorActionPreference = 'Stop'
|
||||
$blockingRules = @(Get-NetFirewallApplicationFilter -Program ${quotePowerShell(executablePath)} -ErrorAction SilentlyContinue | Get-NetFirewallRule | Where-Object { $_.Enabled -eq 'True' -and $_.Direction -eq 'Inbound' -and $_.Action -eq 'Block' })
|
||||
foreach ($rule in $blockingRules) {
|
||||
$portFilter = $rule | Get-NetFirewallPortFilter
|
||||
$protocol = [string]$portFilter.Protocol
|
||||
$profile = [string]$rule.Profile
|
||||
$portMatches = @($portFilter.LocalPort | Where-Object { [string]$_ -eq 'Any' -or [string]$_ -eq '${port}' }).Count -gt 0
|
||||
if (($protocol -eq 'Any' -or $protocol -eq 'TCP' -or $protocol -eq '6') -and ($profile -eq 'Any' -or $profile -match 'Private') -and $portMatches) {
|
||||
$rule | Remove-NetFirewallRule
|
||||
}
|
||||
}
|
||||
Get-NetFirewallRule -Name ${quotePowerShell(FIREWALL_RULE_NAME)} -ErrorAction SilentlyContinue | Remove-NetFirewallRule
|
||||
New-NetFirewallRule -Name ${quotePowerShell(FIREWALL_RULE_NAME)} -DisplayName ${quotePowerShell(FIREWALL_RULE_DISPLAY_NAME)} -Description 'Allows Orca Mobile to connect to this Orca desktop on private networks.' -Direction Inbound -Action Allow -Enabled True -Profile Private -Protocol TCP -LocalPort ${port} -Program ${quotePowerShell(executablePath)} -EdgeTraversalPolicy Block | Out-Null`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3180,6 +3180,7 @@ export type PreloadApi = {
|
|||
supported: true
|
||||
port: number
|
||||
ruleAllowed: boolean
|
||||
blockingRuleDetected: boolean
|
||||
privateFirewallEnabled: boolean
|
||||
networkCategory: 'private' | 'public' | 'domain' | 'unknown'
|
||||
inspectionAvailable: boolean
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import '@testing-library/jest-dom/vitest'
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
import { cleanup, render, screen, waitFor } from '@testing-library/react'
|
||||
import { act, cleanup, render, screen, waitFor } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import { WindowsFirewallNotice } from './WindowsFirewallNotice'
|
||||
|
||||
|
|
@ -28,6 +28,7 @@ describe('WindowsFirewallNotice', () => {
|
|||
supported: true,
|
||||
port: 6768,
|
||||
ruleAllowed: false,
|
||||
blockingRuleDetected: false,
|
||||
privateFirewallEnabled: true,
|
||||
networkCategory: 'private',
|
||||
inspectionAvailable: true
|
||||
|
|
@ -45,15 +46,28 @@ describe('WindowsFirewallNotice', () => {
|
|||
|
||||
it('repairs only after explicit user action and hides after success', async () => {
|
||||
const repairWindowsFirewall = vi.fn().mockResolvedValue({ ok: true })
|
||||
setMobileApi({
|
||||
getWindowsFirewallStatus: vi.fn().mockResolvedValue({
|
||||
const getWindowsFirewallStatus = vi
|
||||
.fn()
|
||||
.mockResolvedValueOnce({
|
||||
supported: true,
|
||||
port: 6768,
|
||||
ruleAllowed: false,
|
||||
blockingRuleDetected: false,
|
||||
privateFirewallEnabled: true,
|
||||
networkCategory: 'private',
|
||||
inspectionAvailable: true
|
||||
}),
|
||||
})
|
||||
.mockResolvedValueOnce({
|
||||
supported: true,
|
||||
port: 6768,
|
||||
ruleAllowed: true,
|
||||
blockingRuleDetected: false,
|
||||
privateFirewallEnabled: true,
|
||||
networkCategory: 'private',
|
||||
inspectionAvailable: true
|
||||
})
|
||||
setMobileApi({
|
||||
getWindowsFirewallStatus,
|
||||
repairWindowsFirewall
|
||||
})
|
||||
const user = userEvent.setup()
|
||||
|
|
@ -61,11 +75,77 @@ describe('WindowsFirewallNotice', () => {
|
|||
|
||||
await user.click(await screen.findByRole('button', { name: /allow phone connections/i }))
|
||||
expect(repairWindowsFirewall).toHaveBeenCalledTimes(1)
|
||||
await waitFor(() => expect(getWindowsFirewallStatus).toHaveBeenCalledTimes(2))
|
||||
await waitFor(() =>
|
||||
expect(screen.queryByText(/allow phone connections through/i)).not.toBeInTheDocument()
|
||||
)
|
||||
})
|
||||
|
||||
it('reports an overriding Block rule and stays actionable if repair cannot clear it', async () => {
|
||||
const blockedStatus = {
|
||||
supported: true,
|
||||
port: 6768,
|
||||
ruleAllowed: false,
|
||||
blockingRuleDetected: true,
|
||||
privateFirewallEnabled: true,
|
||||
networkCategory: 'private',
|
||||
inspectionAvailable: true
|
||||
}
|
||||
const getWindowsFirewallStatus = vi.fn().mockResolvedValue(blockedStatus)
|
||||
const repairWindowsFirewall = vi.fn().mockResolvedValue({ ok: true })
|
||||
setMobileApi({ getWindowsFirewallStatus, repairWindowsFirewall })
|
||||
const user = userEvent.setup()
|
||||
render(<WindowsFirewallNotice pairingReady address="192.168.0.108" />)
|
||||
|
||||
expect(await screen.findByText(/Windows may be blocking Orca Mobile/i)).toBeInTheDocument()
|
||||
expect(screen.getByText(/Block rule can override/i)).toBeInTheDocument()
|
||||
await user.click(screen.getByRole('button', { name: /repair firewall access/i }))
|
||||
|
||||
await waitFor(() => expect(getWindowsFirewallStatus).toHaveBeenCalledTimes(2))
|
||||
expect(screen.getByText(/Windows may be blocking Orca Mobile/i)).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('ignores a stale inspection that resolves after a newer result', async () => {
|
||||
const blockedStatus = {
|
||||
supported: true,
|
||||
port: 6768,
|
||||
ruleAllowed: false,
|
||||
blockingRuleDetected: true,
|
||||
privateFirewallEnabled: true,
|
||||
networkCategory: 'private',
|
||||
inspectionAvailable: true
|
||||
}
|
||||
const clearedStatus = { ...blockedStatus, ruleAllowed: true, blockingRuleDetected: false }
|
||||
let resolveStale: (status: typeof blockedStatus) => void = () => {}
|
||||
const getWindowsFirewallStatus = vi
|
||||
.fn()
|
||||
.mockResolvedValueOnce(blockedStatus)
|
||||
.mockImplementationOnce(
|
||||
() =>
|
||||
new Promise((resolve) => {
|
||||
resolveStale = resolve
|
||||
})
|
||||
)
|
||||
.mockResolvedValueOnce(clearedStatus)
|
||||
setMobileApi({ getWindowsFirewallStatus })
|
||||
render(<WindowsFirewallNotice pairingReady address="192.168.0.108" />)
|
||||
expect(await screen.findByText(/Windows may be blocking Orca Mobile/i)).toBeInTheDocument()
|
||||
|
||||
// Why: UAC elevation bounces window focus, so an older in-flight
|
||||
// inspection can resolve after a newer one and must not win.
|
||||
window.dispatchEvent(new Event('focus'))
|
||||
window.dispatchEvent(new Event('focus'))
|
||||
await waitFor(() => expect(getWindowsFirewallStatus).toHaveBeenCalledTimes(3))
|
||||
await waitFor(() =>
|
||||
expect(screen.queryByText(/Windows may be blocking Orca Mobile/i)).not.toBeInTheDocument()
|
||||
)
|
||||
|
||||
await act(async () => {
|
||||
resolveStale(blockedStatus)
|
||||
})
|
||||
expect(screen.queryByText(/Windows may be blocking Orca Mobile/i)).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('does not offer a firewall rule while the selected network is public', async () => {
|
||||
const openWindowsNetworkSettings = vi.fn().mockResolvedValue(true)
|
||||
setMobileApi({
|
||||
|
|
@ -73,6 +153,7 @@ describe('WindowsFirewallNotice', () => {
|
|||
supported: true,
|
||||
port: 6768,
|
||||
ruleAllowed: true,
|
||||
blockingRuleDetected: false,
|
||||
privateFirewallEnabled: false,
|
||||
networkCategory: 'public',
|
||||
inspectionAvailable: true
|
||||
|
|
@ -95,6 +176,7 @@ describe('WindowsFirewallNotice', () => {
|
|||
supported: true,
|
||||
port: 6768,
|
||||
ruleAllowed: false,
|
||||
blockingRuleDetected: false,
|
||||
privateFirewallEnabled: true,
|
||||
networkCategory: 'domain',
|
||||
inspectionAvailable: true
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { CircleAlert, Loader2, ShieldCheck } from 'lucide-react'
|
||||
import { toast } from 'sonner'
|
||||
import type { WindowsMobileFirewallStatus } from '../../../../shared/windows-mobile-firewall'
|
||||
|
|
@ -21,23 +21,29 @@ export function WindowsFirewallNotice({
|
|||
const [status, setStatus] = useState<WindowsMobileFirewallStatus | null>(null)
|
||||
const [repairing, setRepairing] = useState(false)
|
||||
const mountedRef = useMountedRef()
|
||||
const inspectIdRef = useRef(0)
|
||||
|
||||
const inspect = useCallback(async () => {
|
||||
const inspect = useCallback(async (): Promise<WindowsMobileFirewallStatus | null> => {
|
||||
// Why: UAC elevation steals and returns window focus, so a focus-triggered
|
||||
// inspection can race the post-repair one; only the latest result may win.
|
||||
const inspectId = ++inspectIdRef.current
|
||||
if (!pairingReady) {
|
||||
setStatus(null)
|
||||
return
|
||||
return null
|
||||
}
|
||||
try {
|
||||
const next = await window.api.mobile.getWindowsFirewallStatus(
|
||||
address ? { address } : undefined
|
||||
)
|
||||
if (mountedRef.current) {
|
||||
if (mountedRef.current && inspectIdRef.current === inspectId) {
|
||||
setStatus(next)
|
||||
}
|
||||
return next
|
||||
} catch {
|
||||
if (mountedRef.current) {
|
||||
if (mountedRef.current && inspectIdRef.current === inspectId) {
|
||||
setStatus(null)
|
||||
}
|
||||
return null
|
||||
}
|
||||
}, [address, mountedRef, pairingReady])
|
||||
|
||||
|
|
@ -52,11 +58,16 @@ export function WindowsFirewallNotice({
|
|||
}
|
||||
const firewallStatus = status
|
||||
const networkIsPublic = firewallStatus.networkCategory === 'public'
|
||||
const blockingRuleDetected = firewallStatus.blockingRuleDetected
|
||||
// Why: a Private-profile allow rule cannot help on managed domain networks.
|
||||
if (!pairingReady || firewallStatus.networkCategory === 'domain') {
|
||||
return null
|
||||
}
|
||||
if (!networkIsPublic && (firewallStatus.ruleAllowed || !firewallStatus.privateFirewallEnabled)) {
|
||||
if (
|
||||
!networkIsPublic &&
|
||||
(!firewallStatus.privateFirewallEnabled ||
|
||||
(firewallStatus.ruleAllowed && !blockingRuleDetected))
|
||||
) {
|
||||
return null
|
||||
}
|
||||
|
||||
|
|
@ -68,11 +79,32 @@ export function WindowsFirewallNotice({
|
|||
return
|
||||
}
|
||||
if (result.ok) {
|
||||
setStatus({ ...firewallStatus, ruleAllowed: true })
|
||||
toast.success(
|
||||
// Why: elevation success only confirms the script ran; managed policy
|
||||
// can still leave an overriding Block rule in effect.
|
||||
const next = await inspect()
|
||||
if (!mountedRef.current) {
|
||||
return
|
||||
}
|
||||
if (
|
||||
next?.supported &&
|
||||
(!next.privateFirewallEnabled ||
|
||||
(next.ruleAllowed && !next.blockingRuleDetected && next.inspectionAvailable))
|
||||
) {
|
||||
toast.success(
|
||||
translate(
|
||||
'auto.components.mobile.WindowsFirewallNotice.repair-success',
|
||||
'Windows Firewall now allows Orca Mobile on private networks'
|
||||
)
|
||||
)
|
||||
return
|
||||
}
|
||||
if (!next) {
|
||||
setStatus(firewallStatus)
|
||||
}
|
||||
toast.error(
|
||||
translate(
|
||||
'auto.components.mobile.WindowsFirewallNotice.repair-success',
|
||||
'Windows Firewall now allows Orca Mobile on private networks'
|
||||
'auto.components.mobile.WindowsFirewallNotice.repair-unverified',
|
||||
'Windows Firewall access could not be verified'
|
||||
)
|
||||
)
|
||||
return
|
||||
|
|
@ -81,7 +113,7 @@ export function WindowsFirewallNotice({
|
|||
toast.error(
|
||||
translate(
|
||||
'auto.components.mobile.WindowsFirewallNotice.repair-failed',
|
||||
'Could not add the Windows Firewall rule'
|
||||
'Could not update the Windows Firewall rules'
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
@ -90,7 +122,7 @@ export function WindowsFirewallNotice({
|
|||
toast.error(
|
||||
translate(
|
||||
'auto.components.mobile.WindowsFirewallNotice.repair-failed',
|
||||
'Could not add the Windows Firewall rule'
|
||||
'Could not update the Windows Firewall rules'
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
@ -113,10 +145,15 @@ export function WindowsFirewallNotice({
|
|||
'auto.components.mobile.WindowsFirewallNotice.public-title',
|
||||
'Windows marks this network as public'
|
||||
)
|
||||
: translate(
|
||||
'auto.components.mobile.WindowsFirewallNotice.missing-title',
|
||||
'Allow phone connections through Windows Firewall'
|
||||
)}
|
||||
: blockingRuleDetected
|
||||
? translate(
|
||||
'auto.components.mobile.WindowsFirewallNotice.blocked-title',
|
||||
'Windows may be blocking Orca Mobile'
|
||||
)
|
||||
: translate(
|
||||
'auto.components.mobile.WindowsFirewallNotice.missing-title',
|
||||
'Allow phone connections through Windows Firewall'
|
||||
)}
|
||||
</p>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{networkIsPublic
|
||||
|
|
@ -124,11 +161,17 @@ export function WindowsFirewallNotice({
|
|||
'auto.components.mobile.WindowsFirewallNotice.public-description',
|
||||
'Change this trusted Wi-Fi network to Private before allowing Orca Mobile connections.'
|
||||
)
|
||||
: translate(
|
||||
'auto.components.mobile.WindowsFirewallNotice.missing-description',
|
||||
'Windows may block the pairing server. Add a rule for this Orca app and TCP port {{port}} on Private networks.',
|
||||
{ port: firewallStatus.port }
|
||||
)}
|
||||
: blockingRuleDetected
|
||||
? translate(
|
||||
'auto.components.mobile.WindowsFirewallNotice.blocked-description',
|
||||
'An existing inbound Block rule can override the pairing exception. Repair removes conflicting TCP rules for this Orca app, then allows port {{port}} on Private networks.',
|
||||
{ port: firewallStatus.port }
|
||||
)
|
||||
: translate(
|
||||
'auto.components.mobile.WindowsFirewallNotice.missing-description',
|
||||
'Windows may block the pairing server. Add a rule for this Orca app and TCP port {{port}} on Private networks.',
|
||||
{ port: firewallStatus.port }
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
{networkIsPublic ? (
|
||||
|
|
@ -155,10 +198,15 @@ export function WindowsFirewallNotice({
|
|||
'auto.components.mobile.WindowsFirewallNotice.waiting',
|
||||
'Waiting for Windows…'
|
||||
)
|
||||
: translate(
|
||||
'auto.components.mobile.WindowsFirewallNotice.allow',
|
||||
'Allow phone connections'
|
||||
)}
|
||||
: blockingRuleDetected
|
||||
? translate(
|
||||
'auto.components.mobile.WindowsFirewallNotice.repair',
|
||||
'Repair firewall access'
|
||||
)
|
||||
: translate(
|
||||
'auto.components.mobile.WindowsFirewallNotice.allow',
|
||||
'Allow phone connections'
|
||||
)}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -10703,14 +10703,18 @@
|
|||
},
|
||||
"WindowsFirewallNotice": {
|
||||
"repair-success": "Windows Firewall now allows Orca Mobile on private networks",
|
||||
"repair-failed": "Could not add the Windows Firewall rule",
|
||||
"repair-failed": "Could not update the Windows Firewall rules",
|
||||
"public-title": "Windows marks this network as public",
|
||||
"missing-title": "Allow phone connections through Windows Firewall",
|
||||
"public-description": "Change this trusted Wi-Fi network to Private before allowing Orca Mobile connections.",
|
||||
"missing-description": "Windows may block the pairing server. Add a rule for this Orca app and TCP port {{port}} on Private networks.",
|
||||
"open-settings": "Open network settings",
|
||||
"waiting": "Waiting for Windows…",
|
||||
"allow": "Allow phone connections"
|
||||
"allow": "Allow phone connections",
|
||||
"repair-unverified": "Windows Firewall access could not be verified",
|
||||
"blocked-title": "Windows may be blocking Orca Mobile",
|
||||
"blocked-description": "An existing inbound Block rule can override the pairing exception. Repair removes conflicting TCP rules for this Orca app, then allows port {{port}} on Private networks.",
|
||||
"repair": "Repair firewall access"
|
||||
}
|
||||
},
|
||||
"gitlab": {
|
||||
|
|
|
|||
|
|
@ -10703,14 +10703,18 @@
|
|||
},
|
||||
"WindowsFirewallNotice": {
|
||||
"repair-success": "Windows Firewall now allows Orca Mobile on private networks",
|
||||
"repair-failed": "Could not add the Windows Firewall rule",
|
||||
"repair-failed": "Could not update the Windows Firewall rules",
|
||||
"public-title": "Windows marks this network as public",
|
||||
"missing-title": "Allow phone connections through Windows Firewall",
|
||||
"public-description": "Change this trusted Wi-Fi network to Private before allowing Orca Mobile connections.",
|
||||
"missing-description": "Windows may block the pairing server. Add a rule for this Orca app and TCP port {{port}} on Private networks.",
|
||||
"open-settings": "Open network settings",
|
||||
"waiting": "Waiting for Windows…",
|
||||
"allow": "Allow phone connections"
|
||||
"allow": "Allow phone connections",
|
||||
"repair-unverified": "Windows Firewall access could not be verified",
|
||||
"blocked-title": "Windows may be blocking Orca Mobile",
|
||||
"blocked-description": "An existing inbound Block rule can override the pairing exception. Repair removes conflicting TCP rules for this Orca app, then allows port {{port}} on Private networks.",
|
||||
"repair": "Repair firewall access"
|
||||
}
|
||||
},
|
||||
"gitlab": {
|
||||
|
|
|
|||
|
|
@ -10703,14 +10703,18 @@
|
|||
},
|
||||
"WindowsFirewallNotice": {
|
||||
"repair-success": "Windows Firewall now allows Orca Mobile on private networks",
|
||||
"repair-failed": "Could not add the Windows Firewall rule",
|
||||
"repair-failed": "Could not update the Windows Firewall rules",
|
||||
"public-title": "Windows marks this network as public",
|
||||
"missing-title": "Allow phone connections through Windows Firewall",
|
||||
"public-description": "Change this trusted Wi-Fi network to Private before allowing Orca Mobile connections.",
|
||||
"missing-description": "Windows may block the pairing server. Add a rule for this Orca app and TCP port {{port}} on Private networks.",
|
||||
"open-settings": "Open network settings",
|
||||
"waiting": "Waiting for Windows…",
|
||||
"allow": "Allow phone connections"
|
||||
"allow": "Allow phone connections",
|
||||
"repair-unverified": "Windows Firewall access could not be verified",
|
||||
"blocked-title": "Windows may be blocking Orca Mobile",
|
||||
"blocked-description": "An existing inbound Block rule can override the pairing exception. Repair removes conflicting TCP rules for this Orca app, then allows port {{port}} on Private networks.",
|
||||
"repair": "Repair firewall access"
|
||||
}
|
||||
},
|
||||
"gitlab": {
|
||||
|
|
|
|||
|
|
@ -10703,14 +10703,18 @@
|
|||
},
|
||||
"WindowsFirewallNotice": {
|
||||
"repair-success": "Windows Firewall now allows Orca Mobile on private networks",
|
||||
"repair-failed": "Could not add the Windows Firewall rule",
|
||||
"repair-failed": "Could not update the Windows Firewall rules",
|
||||
"public-title": "Windows marks this network as public",
|
||||
"missing-title": "Allow phone connections through Windows Firewall",
|
||||
"public-description": "Change this trusted Wi-Fi network to Private before allowing Orca Mobile connections.",
|
||||
"missing-description": "Windows may block the pairing server. Add a rule for this Orca app and TCP port {{port}} on Private networks.",
|
||||
"open-settings": "Open network settings",
|
||||
"waiting": "Waiting for Windows…",
|
||||
"allow": "Allow phone connections"
|
||||
"allow": "Allow phone connections",
|
||||
"repair-unverified": "Windows Firewall access could not be verified",
|
||||
"blocked-title": "Windows may be blocking Orca Mobile",
|
||||
"blocked-description": "An existing inbound Block rule can override the pairing exception. Repair removes conflicting TCP rules for this Orca app, then allows port {{port}} on Private networks.",
|
||||
"repair": "Repair firewall access"
|
||||
}
|
||||
},
|
||||
"gitlab": {
|
||||
|
|
|
|||
|
|
@ -10703,14 +10703,18 @@
|
|||
},
|
||||
"WindowsFirewallNotice": {
|
||||
"repair-success": "Windows Firewall now allows Orca Mobile on private networks",
|
||||
"repair-failed": "Could not add the Windows Firewall rule",
|
||||
"repair-failed": "Could not update the Windows Firewall rules",
|
||||
"public-title": "Windows marks this network as public",
|
||||
"missing-title": "Allow phone connections through Windows Firewall",
|
||||
"public-description": "Change this trusted Wi-Fi network to Private before allowing Orca Mobile connections.",
|
||||
"missing-description": "Windows may block the pairing server. Add a rule for this Orca app and TCP port {{port}} on Private networks.",
|
||||
"open-settings": "Open network settings",
|
||||
"waiting": "Waiting for Windows…",
|
||||
"allow": "Allow phone connections"
|
||||
"allow": "Allow phone connections",
|
||||
"repair-unverified": "Windows Firewall access could not be verified",
|
||||
"blocked-title": "Windows may be blocking Orca Mobile",
|
||||
"blocked-description": "An existing inbound Block rule can override the pairing exception. Repair removes conflicting TCP rules for this Orca app, then allows port {{port}} on Private networks.",
|
||||
"repair": "Repair firewall access"
|
||||
}
|
||||
},
|
||||
"gitlab": {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ export type WindowsMobileFirewallStatus =
|
|||
supported: true
|
||||
port: number
|
||||
ruleAllowed: boolean
|
||||
blockingRuleDetected: boolean
|
||||
privateFirewallEnabled: boolean
|
||||
networkCategory: WindowsNetworkCategory
|
||||
inspectionAvailable: boolean
|
||||
|
|
|
|||
Loading…
Reference in New Issue