2
0
mirror of https://github.com/KDE/kdeconnect-android synced 2025-08-22 09:58:08 +00:00

Fix trusted networks

## Summary
1) Fix the code responsible for loading the trusted network list.
2) The old `#_#` delimiter has been replaced with a less likely NUL character. This requires re-adding trusted networks, so I can revert it if necessary.
3) Ignore incoming identity packets on untrusted devices if they come from an untrusted device.

BUG: 492302

## Test Plan

### Before:
1) Trusted networks were completely broken, an would show variations of `#` and `_` on the list due to a bug in the splitting code.
2) Any network with `#_#` in the SSID - although unlikely - would not be possible to use as a trusted network.
3) The device was still discoverable on an untrusted network by manually refreshing the devices list.

### After:
1) Trusted networks now load the SSID list correctly.
2) Networks with `#_#` in the SSID can be added as trusted networks.
3) The device is no longer discoverable on an untrusted network.
This commit is contained in:
Marko Zajc 2024-09-21 22:24:46 +00:00 committed by Philip Cohn-Cort
parent ee7d4a1f05
commit db615b82df
2 changed files with 30 additions and 13 deletions

View File

@ -109,7 +109,14 @@ public class LanLinkProvider extends BaseLinkProvider {
}
Log.i("KDE/LanLinkProvider", "identity packet received from a TCP connection from " + networkPacket.getString("deviceName"));
identityPacketReceived(networkPacket, socket, LanLink.ConnectionStarted.Locally);
boolean deviceTrusted = isDeviceTrusted(networkPacket.getString("deviceId"));
if (!deviceTrusted && !TrustedNetworkHelper.isTrustedNetwork(context)) {
Log.i("KDE/LanLinkProvider", "Ignoring identity packet because the device is not trusted and I'm not on a trusted network.");
return;
}
identityPacketReceived(networkPacket, socket, LanLink.ConnectionStarted.Locally, deviceTrusted);
}
//I've received their broadcast and should connect to their TCP socket and send my identity.
@ -149,6 +156,12 @@ public class LanLinkProvider extends BaseLinkProvider {
Log.i("KDE/LanLinkProvider", "Broadcast identity packet received from " + identityPacket.getString("deviceName"));
boolean deviceTrusted = isDeviceTrusted(identityPacket.getString("deviceId"));
if (!deviceTrusted && !TrustedNetworkHelper.isTrustedNetwork(context)) {
Log.i("KDE/LanLinkProvider", "Ignoring identity packet because the device is not trusted and I'm not on a trusted network.");
return;
}
SocketFactory socketFactory = SocketFactory.getDefault();
Socket socket = socketFactory.createSocket(address, tcpPort);
configureSocket(socket);
@ -160,7 +173,7 @@ public class LanLinkProvider extends BaseLinkProvider {
out.write(myIdentity.serialize().getBytes());
out.flush();
identityPacketReceived(identityPacket, socket, LanLink.ConnectionStarted.Remotely);
identityPacketReceived(identityPacket, socket, LanLink.ConnectionStarted.Remotely, deviceTrusted);
}
private void configureSocket(Socket socket) {
@ -171,6 +184,11 @@ public class LanLinkProvider extends BaseLinkProvider {
}
}
private boolean isDeviceTrusted(String deviceId) {
SharedPreferences preferences = context.getSharedPreferences("trusted_devices", Context.MODE_PRIVATE);
return preferences.getBoolean(deviceId, false);
}
/**
* Called when a new 'identity' packet is received. Those are passed here by
* {@link #tcpPacketReceived(Socket)} and {@link #udpPacketReceived(DatagramPacket)}.
@ -184,9 +202,10 @@ public class LanLinkProvider extends BaseLinkProvider {
* @param identityPacket identity of a remote device
* @param socket a new Socket, which should be used to receive packets from the remote device
* @param connectionStarted which side started this connection
* @param deviceTrusted whether the packet comes from a trusted device
*/
@WorkerThread
private void identityPacketReceived(final NetworkPacket identityPacket, final Socket socket, final LanLink.ConnectionStarted connectionStarted) throws IOException {
private void identityPacketReceived(final NetworkPacket identityPacket, final Socket socket, final LanLink.ConnectionStarted connectionStarted, final boolean deviceTrusted) throws IOException {
if (!DeviceInfo.isValidIdentityPacket(identityPacket)) {
Log.w("KDE/LanLinkProvider", "Invalid identity packet received.");
@ -203,10 +222,7 @@ public class LanLinkProvider extends BaseLinkProvider {
// If I'm the TCP server I will be the SSL client and viceversa.
final boolean clientMode = (connectionStarted == LanLink.ConnectionStarted.Locally);
SharedPreferences preferences = context.getSharedPreferences("trusted_devices", Context.MODE_PRIVATE);
boolean isDeviceTrusted = preferences.getBoolean(deviceId, false);
if (isDeviceTrusted && !SslHelper.isCertificateStored(context, deviceId)) {
if (deviceTrusted && !SslHelper.isCertificateStored(context, deviceId)) {
//Device paired with and old version, we can't use it as we lack the certificate
Device device = KdeConnect.getInstance().getDevice(deviceId);
if (device == null) {
@ -214,13 +230,13 @@ public class LanLinkProvider extends BaseLinkProvider {
}
device.unpair();
//Retry as unpaired
identityPacketReceived(identityPacket, socket, connectionStarted);
identityPacketReceived(identityPacket, socket, connectionStarted, deviceTrusted);
}
String deviceName = identityPacket.getString("deviceName", "unknown");
Log.i("KDE/LanLinkProvider", "Starting SSL handshake with " + deviceName + " trusted:" + isDeviceTrusted);
Log.i("KDE/LanLinkProvider", "Starting SSL handshake with " + deviceName + " trusted:" + deviceTrusted);
final SSLSocket sslSocket = SslHelper.convertToSslSocket(context, socket, deviceId, isDeviceTrusted, clientMode);
final SSLSocket sslSocket = SslHelper.convertToSslSocket(context, socket, deviceId, deviceTrusted, clientMode);
sslSocket.addHandshakeCompletedListener(event -> {
String mode = clientMode ? "client" : "server";
try {

View File

@ -19,7 +19,7 @@ class TrustedNetworkHelper(private val context: Context) {
var trustedNetworks: List<String>
get() {
val serializedNetworks = PreferenceManager.getDefaultSharedPreferences(context).getString(KEY_CUSTOM_TRUSTED_NETWORKS, "") ?: ""
return NETWORK_SSID_DELIMITER.split(serializedNetworks).filter { it.isNotEmpty() }
return serializedNetworks.split(NETWORK_SSID_DELIMITER, "#_#" /* TODO remove old delimiter in 2025 */).filter { it.isNotEmpty() }
}
set(value) {
PreferenceManager.getDefaultSharedPreferences(context)
@ -36,7 +36,8 @@ class TrustedNetworkHelper(private val context: Context) {
.putBoolean(KEY_CUSTOM_TRUST_ALL_NETWORKS, value)
.apply()
val hasPermissions: Boolean = ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
val hasPermissions: Boolean
get() = ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
/** @return The current SSID or null if it's not available for any reason */
val currentSSID: String?
@ -61,7 +62,7 @@ class TrustedNetworkHelper(private val context: Context) {
companion object {
private const val KEY_CUSTOM_TRUSTED_NETWORKS = "trusted_network_preference"
private const val KEY_CUSTOM_TRUST_ALL_NETWORKS = "trust_all_network_preference"
private const val NETWORK_SSID_DELIMITER = "#_#"
private const val NETWORK_SSID_DELIMITER = "\u0000"
private const val NOT_AVAILABLE_SSID_RESULT = "<unknown ssid>"
@JvmStatic