summaryrefslogtreecommitdiffhomepage
path: root/gui/src
diff options
context:
space:
mode:
authorOskar <oskar@mullvad.net>2024-10-14 14:06:54 +0200
committerOskar <oskar@mullvad.net>2024-10-14 14:06:54 +0200
commit8f5955ba3f0f92785e652de900a35768957bb390 (patch)
treede42399c9279c03dade9d87a158b143ba0abd612 /gui/src
parent5fb364b270c104fec7ad68a90824a69cea1e98e8 (diff)
parent1d055d19e5f0e5465677d1a6fa93812c642af8ac (diff)
downloadmullvadvpn-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.tsx24
-rw-r--r--gui/src/renderer/components/VpnSettings.tsx41
-rw-r--r--gui/src/renderer/components/select-location/RelayListContext.tsx14
-rw-r--r--gui/src/renderer/lib/filter-locations.ts8
-rw-r--r--gui/src/renderer/lib/utilityHooks.ts14
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;