diff options
| author | Oskar <oskar@mullvad.net> | 2024-10-14 14:06:54 +0200 |
|---|---|---|
| committer | Oskar <oskar@mullvad.net> | 2024-10-14 14:06:54 +0200 |
| commit | 8f5955ba3f0f92785e652de900a35768957bb390 (patch) | |
| tree | de42399c9279c03dade9d87a158b143ba0abd612 /gui/src | |
| parent | 5fb364b270c104fec7ad68a90824a69cea1e98e8 (diff) | |
| parent | 1d055d19e5f0e5465677d1a6fa93812c642af8ac (diff) | |
| download | mullvadvpn-8f5955ba3f0f92785e652de900a35768957bb390.tar.xz mullvadvpn-8f5955ba3f0f92785e652de900a35768957bb390.zip | |
Merge branch 'prevent-user-from-enabling-openvpn-when-a-core-privacy-des-1272'
Diffstat (limited to 'gui/src')
| -rw-r--r-- | gui/src/renderer/components/Filter.tsx | 24 | ||||
| -rw-r--r-- | gui/src/renderer/components/VpnSettings.tsx | 41 | ||||
| -rw-r--r-- | gui/src/renderer/components/select-location/RelayListContext.tsx | 14 | ||||
| -rw-r--r-- | gui/src/renderer/lib/filter-locations.ts | 8 | ||||
| -rw-r--r-- | gui/src/renderer/lib/utilityHooks.ts | 14 |
5 files changed, 85 insertions, 16 deletions
diff --git a/gui/src/renderer/components/Filter.tsx b/gui/src/renderer/components/Filter.tsx index d989cbca95..b3c223bc38 100644 --- a/gui/src/renderer/components/Filter.tsx +++ b/gui/src/renderer/components/Filter.tsx @@ -11,9 +11,9 @@ import { filterLocationsByEndPointType, } from '../lib/filter-locations'; import { useHistory } from '../lib/history'; -import { useBoolean, useNormalRelaySettings } from '../lib/utilityHooks'; +import { useBoolean, useNormalRelaySettings, useTunnelProtocol } from '../lib/utilityHooks'; import { IRelayLocationCountryRedux } from '../redux/settings/reducers'; -import { IReduxState, useSelector } from '../redux/store'; +import { useSelector } from '../redux/store'; import Accordion from './Accordion'; import * as AppButton from './AppButton'; import { AriaInputGroup, AriaLabel } from './AriaGroup'; @@ -40,7 +40,7 @@ export default function Filter() { const history = useHistory(); const relaySettingsUpdater = useRelaySettingsUpdater(); - const initialProviders = useSelector(providersSelector); + const initialProviders = useProviders(); const [providers, setProviders] = useState<Record<string, boolean>>(initialProviders); // The daemon expects the value to be an empty list if all are selected. @@ -121,6 +121,7 @@ export default function Filter() { // Returns only the ownership options that are compatible with the other filters function useFilteredOwnershipOptions(providers: string[], ownership: Ownership): Ownership[] { const relaySettings = useNormalRelaySettings(); + const tunnelProtocol = useTunnelProtocol(); const bridgeState = useSelector((state) => state.settings.bridgeState); const locations = useSelector((state) => state.settings.relayLocations); @@ -130,6 +131,7 @@ function useFilteredOwnershipOptions(providers: string[], ownership: Ownership): const relayListForEndpointType = filterLocationsByEndPointType( locations, endpointType, + tunnelProtocol, relaySettings, ); const relaylistForFilters = filterLocations(relayListForEndpointType, ownership, providers); @@ -155,6 +157,7 @@ function useFilteredOwnershipOptions(providers: string[], ownership: Ownership): // Returns only the providers that are compatible with the other filters export function useFilteredProviders(providers: string[], ownership: Ownership): string[] { const relaySettings = useNormalRelaySettings(); + const tunnelProtocol = useTunnelProtocol(); const bridgeState = useSelector((state) => state.settings.bridgeState); const locations = useSelector((state) => state.settings.relayLocations); @@ -164,6 +167,7 @@ export function useFilteredProviders(providers: string[], ownership: Ownership): const relayListForEndpointType = filterLocationsByEndPointType( locations, endpointType, + tunnelProtocol, relaySettings, ); const relaylistForFilters = filterLocations(relayListForEndpointType, ownership, providers); @@ -181,15 +185,19 @@ function providersFromRelays(relays: IRelayLocationCountryRedux[]) { return removeDuplicates(providers).sort((a, b) => a.localeCompare(b)); } -function providersSelector(state: IReduxState): Record<string, boolean> { - const relaySettings = - 'normal' in state.settings.relaySettings ? state.settings.relaySettings.normal : undefined; +function useProviders(): Record<string, boolean> { + const tunnelProtocol = useTunnelProtocol(); + const relaySettings = useNormalRelaySettings(); + const relayLocations = useSelector((state) => state.settings.relayLocations); + const bridgeState = useSelector((state) => state.settings.bridgeState); const providerConstraint = relaySettings?.providers ?? []; - const endpointType = state.settings.bridgeState === 'on' ? EndpointType.any : EndpointType.exit; + const endpointType = + tunnelProtocol === 'openvpn' && bridgeState === 'on' ? EndpointType.any : EndpointType.exit; const relays = filterLocationsByEndPointType( - state.settings.relayLocations, + relayLocations, endpointType, + tunnelProtocol, relaySettings, ); const providers = providersFromRelays(relays); diff --git a/gui/src/renderer/components/VpnSettings.tsx b/gui/src/renderer/components/VpnSettings.tsx index 951b17a567..d0253ef480 100644 --- a/gui/src/renderer/components/VpnSettings.tsx +++ b/gui/src/renderer/components/VpnSettings.tsx @@ -11,7 +11,7 @@ import { useRelaySettingsUpdater } from '../lib/constraint-updater'; import { useHistory } from '../lib/history'; import { formatHtml } from '../lib/html-formatter'; import { RoutePath } from '../lib/routes'; -import { useBoolean } from '../lib/utilityHooks'; +import { useBoolean, useTunnelProtocol } from '../lib/utilityHooks'; import { RelaySettingsRedux } from '../redux/settings/reducers'; import { useSelector } from '../redux/store'; import * as AppButton from './AppButton'; @@ -684,6 +684,25 @@ function TunnelProtocolSetting() { ); const relaySettingsUpdater = useRelaySettingsUpdater(); + const relaySettings = useSelector((state) => state.settings.relaySettings); + const multihop = 'normal' in relaySettings ? relaySettings.normal.wireguard.useMultihop : false; + const daita = useSelector((state) => state.settings.wireguard.daita?.enabled ?? false); + const quantumResistant = useSelector((state) => state.settings.wireguard.quantumResistant); + const openVpnDisabled = daita || multihop || quantumResistant; + + const featuresToDisableForOpenVpn = []; + if (daita) { + featuresToDisableForOpenVpn.push(strings.daita); + } + if (multihop) { + featuresToDisableForOpenVpn.push(messages.pgettext('wireguard-settings-view', 'Multihop')); + } + if (quantumResistant) { + featuresToDisableForOpenVpn.push( + messages.pgettext('wireguard-settings-view', 'Quantum-resistant tunnel'), + ); + } + const setTunnelProtocol = useCallback( async (tunnelProtocol: TunnelProtocol | null) => { try { @@ -708,6 +727,7 @@ function TunnelProtocolSetting() { { label: strings.openvpn, value: 'openvpn', + disabled: openVpnDisabled, }, ], [], @@ -724,6 +744,21 @@ function TunnelProtocolSetting() { automaticValue={null} /> </StyledSelectorContainer> + {openVpnDisabled ? ( + <Cell.CellFooter> + <AriaDescription> + <Cell.CellFooterText> + {sprintf( + messages.pgettext( + 'vpn-settings-view', + 'To select %(openvpn)s, please disable these settings: %(featureList)s.', + ), + { openvpn: strings.openvpn, featureList: featuresToDisableForOpenVpn.join(', ') }, + )} + </Cell.CellFooterText> + </AriaDescription> + </Cell.CellFooter> + ) : null} </AriaInputGroup> ); } @@ -764,9 +799,7 @@ function WireguardSettingsButton() { function OpenVpnSettingsButton() { const history = useHistory(); - const tunnelProtocol = useSelector((state) => - mapRelaySettingsToProtocol(state.settings.relaySettings), - ); + const tunnelProtocol = useTunnelProtocol(); const navigate = useCallback(() => history.push(RoutePath.openVpnSettings), [history]); diff --git a/gui/src/renderer/components/select-location/RelayListContext.tsx b/gui/src/renderer/components/select-location/RelayListContext.tsx index c2b29abeea..86fb8de22b 100644 --- a/gui/src/renderer/components/select-location/RelayListContext.tsx +++ b/gui/src/renderer/components/select-location/RelayListContext.tsx @@ -9,7 +9,11 @@ import { getLocationsExpandedBySearch, searchForLocations, } from '../../lib/filter-locations'; -import { useNormalBridgeSettings, useNormalRelaySettings } from '../../lib/utilityHooks'; +import { + useNormalBridgeSettings, + useNormalRelaySettings, + useTunnelProtocol, +} from '../../lib/utilityHooks'; import { IRelayLocationCountryRedux } from '../../redux/settings/reducers'; import { useSelector } from '../../redux/store'; import { useCustomListsRelayList } from './custom-list-helpers'; @@ -66,13 +70,19 @@ export function RelayListContextProvider(props: RelayListContextProviderProps) { const fullRelayList = useSelector((state) => state.settings.relayLocations); const relaySettings = useNormalRelaySettings(); + const tunnelProtocol = useTunnelProtocol(); // Filters the relays to only keep the ones of the desired endpoint type, e.g. "wireguard", // "openvpn" or "bridge" const relayListForEndpointType = useMemo(() => { const endpointType = locationType === LocationType.entry ? EndpointType.entry : EndpointType.exit; - return filterLocationsByEndPointType(fullRelayList, endpointType, relaySettings); + return filterLocationsByEndPointType( + fullRelayList, + endpointType, + tunnelProtocol, + relaySettings, + ); }, [fullRelayList, locationType, relaySettings?.tunnelProtocol]); const relayListForDaita = useMemo(() => { diff --git a/gui/src/renderer/lib/filter-locations.ts b/gui/src/renderer/lib/filter-locations.ts index e559e64096..c3a0f7feb9 100644 --- a/gui/src/renderer/lib/filter-locations.ts +++ b/gui/src/renderer/lib/filter-locations.ts @@ -29,9 +29,13 @@ export enum EndpointType { export function filterLocationsByEndPointType( locations: IRelayLocationCountryRedux[], endpointType: EndpointType, + tunnelProtocol: LiftedConstraint<TunnelProtocol>, relaySettings?: NormalRelaySettingsRedux, ): IRelayLocationCountryRedux[] { - return filterLocationsImpl(locations, getTunnelProtocolFilter(endpointType, relaySettings)); + return filterLocationsImpl( + locations, + getTunnelProtocolFilter(endpointType, tunnelProtocol, relaySettings), + ); } export function filterLocationsByDaita( @@ -74,9 +78,9 @@ export function filterLocations( function getTunnelProtocolFilter( endpointType: EndpointType, + tunnelProtocol: LiftedConstraint<TunnelProtocol>, relaySettings?: NormalRelaySettingsRedux, ): (relay: IRelayLocationRelayRedux) => boolean { - const tunnelProtocol = relaySettings?.tunnelProtocol ?? 'any'; const endpointTypes: Array<RelayEndpointType> = []; if (endpointType !== EndpointType.exit && tunnelProtocol === 'openvpn') { endpointTypes.push('bridge'); diff --git a/gui/src/renderer/lib/utilityHooks.ts b/gui/src/renderer/lib/utilityHooks.ts index 81a5579dd6..be1688f3f3 100644 --- a/gui/src/renderer/lib/utilityHooks.ts +++ b/gui/src/renderer/lib/utilityHooks.ts @@ -1,5 +1,6 @@ import React, { useCallback, useEffect, useRef, useState } from 'react'; +import { LiftedConstraint, TunnelProtocol } from '../../shared/daemon-rpc-types'; import { useSelector } from '../redux/store'; export function useMounted() { @@ -65,6 +66,19 @@ export function useNormalRelaySettings() { return 'normal' in relaySettings ? relaySettings.normal : undefined; } +// Some features are considered core privacy features and when enabled prevent OpenVPN from being +// used. This hook returns the tunnelprotocol with the exception that it always returns WireGuard +// when any of those features are enabled. +export function useTunnelProtocol(): LiftedConstraint<TunnelProtocol> { + const relaySettings = useNormalRelaySettings(); + const multihop = relaySettings?.wireguard.useMultihop ?? false; + const daita = useSelector((state) => state.settings.wireguard.daita?.enabled ?? false); + const quantumResistant = useSelector((state) => state.settings.wireguard.quantumResistant); + const openVpnDisabled = daita || multihop || quantumResistant; + + return openVpnDisabled ? 'wireguard' : (relaySettings?.tunnelProtocol ?? 'any'); +} + export function useNormalBridgeSettings() { const bridgeSettings = useSelector((state) => state.settings.bridgeSettings); return bridgeSettings.normal; |
