Skip to content

Commit

Permalink
Merge branch 'prevent-user-from-enabling-openvpn-when-a-core-privacy-…
Browse files Browse the repository at this point in the history
…des-1272'
  • Loading branch information
raksooo committed Oct 14, 2024
2 parents 5fb364b + 1d055d1 commit 8f5955b
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 16 deletions.
4 changes: 4 additions & 0 deletions gui/locales/messages.pot
Original file line number Diff line number Diff line change
Expand Up @@ -2004,6 +2004,10 @@ msgctxt "vpn-settings-view"
msgid "This might cause issues on certain websites, services, and apps."
msgstr ""

msgctxt "vpn-settings-view"
msgid "To select %(openvpn)s, please disable these settings: %(featureList)s."
msgstr ""

#. Label for settings that enables tracker blocking.
msgctxt "vpn-settings-view"
msgid "Trackers"
Expand Down
24 changes: 16 additions & 8 deletions gui/src/renderer/components/Filter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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.
Expand Down Expand Up @@ -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);

Expand All @@ -130,6 +131,7 @@ function useFilteredOwnershipOptions(providers: string[], ownership: Ownership):
const relayListForEndpointType = filterLocationsByEndPointType(
locations,
endpointType,
tunnelProtocol,
relaySettings,
);
const relaylistForFilters = filterLocations(relayListForEndpointType, ownership, providers);
Expand All @@ -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);

Expand All @@ -164,6 +167,7 @@ export function useFilteredProviders(providers: string[], ownership: Ownership):
const relayListForEndpointType = filterLocationsByEndPointType(
locations,
endpointType,
tunnelProtocol,
relaySettings,
);
const relaylistForFilters = filterLocations(relayListForEndpointType, ownership, providers);
Expand All @@ -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);
Expand Down
41 changes: 37 additions & 4 deletions gui/src/renderer/components/VpnSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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 {
Expand All @@ -708,6 +727,7 @@ function TunnelProtocolSetting() {
{
label: strings.openvpn,
value: 'openvpn',
disabled: openVpnDisabled,
},
],
[],
Expand All @@ -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>
);
}
Expand Down Expand Up @@ -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]);

Expand Down
14 changes: 12 additions & 2 deletions gui/src/renderer/components/select-location/RelayListContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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(() => {
Expand Down
8 changes: 6 additions & 2 deletions gui/src/renderer/lib/filter-locations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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');
Expand Down
14 changes: 14 additions & 0 deletions gui/src/renderer/lib/utilityHooks.ts
Original file line number Diff line number Diff line change
@@ -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() {
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 8f5955b

Please sign in to comment.