mirror of
https://github.com/KDE/kdeconnect-android
synced 2025-08-22 09:58:08 +00:00
Remove compat with protocol 6 with RSA encryption
Since we already removed compat with protocol 7 ^.^u
This commit is contained in:
parent
9a8ae36ef6
commit
168b16527c
@ -26,7 +26,6 @@ import org.kde.kdeconnect.Device;
|
||||
import org.kde.kdeconnect.NetworkPacket;
|
||||
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
||||
@ -90,6 +89,4 @@ public abstract class BaseLink {
|
||||
|
||||
//TO OVERRIDE, should be sync
|
||||
public abstract boolean sendPacket(NetworkPacket np, Device.SendPacketStatusCallback callback);
|
||||
@Deprecated
|
||||
public abstract boolean sendPacketEncrypted(NetworkPacket np, Device.SendPacketStatusCallback callback, PublicKey key);
|
||||
}
|
||||
|
@ -32,7 +32,6 @@ import org.json.JSONObject;
|
||||
import org.kde.kdeconnect.Backends.BaseLink;
|
||||
import org.kde.kdeconnect.Backends.BasePairingHandler;
|
||||
import org.kde.kdeconnect.Device;
|
||||
import org.kde.kdeconnect.Helpers.SecurityHelpers.RsaHelper;
|
||||
import org.kde.kdeconnect.NetworkPacket;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -41,7 +40,6 @@ import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Reader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.PublicKey;
|
||||
import java.util.UUID;
|
||||
|
||||
public class BluetoothLink extends BaseLink {
|
||||
@ -87,14 +85,6 @@ public class BluetoothLink extends BaseLink {
|
||||
return;
|
||||
}
|
||||
|
||||
if (np.getType().equals(NetworkPacket.PACKET_TYPE_ENCRYPTED)) {
|
||||
try {
|
||||
np = RsaHelper.decrypt(np, privateKey);
|
||||
} catch (Exception e) {
|
||||
Log.e("BluetoothLink/receiving", "Exception decrypting the package", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (np.hasPayloadTransferInfo()) {
|
||||
BluetoothSocket transferSocket = null;
|
||||
try {
|
||||
@ -158,16 +148,7 @@ public class BluetoothLink extends BaseLink {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendPacket(NetworkPacket np, Device.SendPacketStatusCallback callback) {
|
||||
return sendPacketInternal(np, callback, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendPacketEncrypted(NetworkPacket np, Device.SendPacketStatusCallback callback, PublicKey key) {
|
||||
return sendPacketInternal(np, callback, key);
|
||||
}
|
||||
|
||||
private boolean sendPacketInternal(NetworkPacket np, final Device.SendPacketStatusCallback callback, PublicKey key) {
|
||||
public boolean sendPacket(NetworkPacket np, final Device.SendPacketStatusCallback callback) {
|
||||
|
||||
/*if (!isConnected()) {
|
||||
Log.e("BluetoothLink", "sendPacketEncrypted failed: not connected");
|
||||
@ -186,15 +167,6 @@ public class BluetoothLink extends BaseLink {
|
||||
np.setPayloadTransferInfo(payloadTransferInfo);
|
||||
}
|
||||
|
||||
if (key != null) {
|
||||
try {
|
||||
np = RsaHelper.encrypt(np, key);
|
||||
} catch (Exception e) {
|
||||
callback.onFailure(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
sendMessage(np);
|
||||
|
||||
if (serverSocket != null) {
|
||||
|
@ -52,7 +52,7 @@ public class BluetoothPairingHandler extends BasePairingHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void packageReceived(NetworkPacket np) throws Exception {
|
||||
public void packageReceived(NetworkPacket np) {
|
||||
|
||||
boolean wantsPair = np.getBoolean("pair");
|
||||
|
||||
|
@ -27,7 +27,6 @@ import org.json.JSONObject;
|
||||
import org.kde.kdeconnect.Backends.BaseLink;
|
||||
import org.kde.kdeconnect.Backends.BasePairingHandler;
|
||||
import org.kde.kdeconnect.Device;
|
||||
import org.kde.kdeconnect.Helpers.SecurityHelpers.RsaHelper;
|
||||
import org.kde.kdeconnect.Helpers.SecurityHelpers.SslHelper;
|
||||
import org.kde.kdeconnect.Helpers.StringsHelper;
|
||||
import org.kde.kdeconnect.NetworkPacket;
|
||||
@ -42,7 +41,6 @@ import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.nio.channels.NotYetConnectedException;
|
||||
import java.security.PublicKey;
|
||||
|
||||
import javax.net.ssl.SSLSocket;
|
||||
|
||||
@ -61,7 +59,7 @@ public class LanLink extends BaseLink {
|
||||
// because it's probably trying to find me and
|
||||
// potentially ask for pairing.
|
||||
|
||||
private volatile Socket socket = null;
|
||||
private volatile SSLSocket socket = null;
|
||||
|
||||
private final LinkDisconnectedCallback callback;
|
||||
|
||||
@ -76,9 +74,9 @@ public class LanLink extends BaseLink {
|
||||
}
|
||||
|
||||
//Returns the old socket
|
||||
public Socket reset(final Socket newSocket, ConnectionStarted connectionSource) throws IOException {
|
||||
public SSLSocket reset(final SSLSocket newSocket, ConnectionStarted connectionSource) throws IOException {
|
||||
|
||||
Socket oldSocket = socket;
|
||||
SSLSocket oldSocket = socket;
|
||||
socket = newSocket;
|
||||
|
||||
this.connectionSource = connectionSource;
|
||||
@ -121,7 +119,7 @@ public class LanLink extends BaseLink {
|
||||
return oldSocket;
|
||||
}
|
||||
|
||||
public LanLink(Context context, String deviceId, LanLinkProvider linkProvider, Socket socket, ConnectionStarted connectionSource) throws IOException {
|
||||
public LanLink(Context context, String deviceId, LanLinkProvider linkProvider, SSLSocket socket, ConnectionStarted connectionSource) throws IOException {
|
||||
super(context, deviceId, linkProvider);
|
||||
callback = linkProvider;
|
||||
reset(socket, connectionSource);
|
||||
@ -139,7 +137,8 @@ public class LanLink extends BaseLink {
|
||||
}
|
||||
|
||||
//Blocking, do not call from main thread
|
||||
private boolean sendPacketInternal(NetworkPacket np, final Device.SendPacketStatusCallback callback, PublicKey key) {
|
||||
@Override
|
||||
public boolean sendPacket(NetworkPacket np, final Device.SendPacketStatusCallback callback) {
|
||||
if (socket == null) {
|
||||
Log.e("KDE/sendPacket", "Not yet connected");
|
||||
callback.onFailure(new NotYetConnectedException());
|
||||
@ -159,11 +158,6 @@ public class LanLink extends BaseLink {
|
||||
server = null;
|
||||
}
|
||||
|
||||
//Encrypt if key provided
|
||||
if (key != null) {
|
||||
np = RsaHelper.encrypt(np, key);
|
||||
}
|
||||
|
||||
//Log.e("LanLink/sendPacket", np.getType());
|
||||
|
||||
//Send body of the network package
|
||||
@ -188,9 +182,7 @@ public class LanLink extends BaseLink {
|
||||
payloadSocket = server.accept();
|
||||
|
||||
//Convert to SSL if needed
|
||||
if (socket instanceof SSLSocket) {
|
||||
payloadSocket = SslHelper.convertToSslSocket(context, payloadSocket, getDeviceId(), true, false);
|
||||
}
|
||||
payloadSocket = SslHelper.convertToSslSocket(context, payloadSocket, getDeviceId(), true, false);
|
||||
|
||||
outputStream = payloadSocket.getOutputStream();
|
||||
inputStream = np.getPayload().getInputStream();
|
||||
@ -240,39 +232,15 @@ public class LanLink extends BaseLink {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Blocking, do not call from main thread
|
||||
@Override
|
||||
public boolean sendPacket(NetworkPacket np, Device.SendPacketStatusCallback callback) {
|
||||
return sendPacketInternal(np, callback, null);
|
||||
}
|
||||
|
||||
//Blocking, do not call from main thread
|
||||
@Override
|
||||
public boolean sendPacketEncrypted(NetworkPacket np, Device.SendPacketStatusCallback callback, PublicKey key) {
|
||||
return sendPacketInternal(np, callback, key);
|
||||
}
|
||||
|
||||
private void receivedNetworkPacket(NetworkPacket np) {
|
||||
|
||||
if (np.getType().equals(NetworkPacket.PACKET_TYPE_ENCRYPTED)) {
|
||||
try {
|
||||
np = RsaHelper.decrypt(np, privateKey);
|
||||
} catch(Exception e) {
|
||||
Log.e("KDE/onPacketReceived","Exception decrypting the package", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (np.hasPayloadTransferInfo()) {
|
||||
Socket payloadSocket = new Socket();
|
||||
try {
|
||||
int tcpPort = np.getPayloadTransferInfo().getInt("port");
|
||||
InetSocketAddress deviceAddress = (InetSocketAddress) socket.getRemoteSocketAddress();
|
||||
payloadSocket.connect(new InetSocketAddress(deviceAddress.getAddress(), tcpPort));
|
||||
// Use ssl if existing link is on ssl
|
||||
if (socket instanceof SSLSocket) {
|
||||
payloadSocket = SslHelper.convertToSslSocket(context, payloadSocket, getDeviceId(), true, true);
|
||||
}
|
||||
payloadSocket = SslHelper.convertToSslSocket(context, payloadSocket, getDeviceId(), true, true);
|
||||
np.setPayload(new NetworkPacket.Payload(payloadSocket, np.getPayloadSize()));
|
||||
} catch (Exception e) {
|
||||
try { payloadSocket.close(); } catch(Exception ignored) { }
|
||||
|
@ -66,9 +66,6 @@ import javax.net.ssl.SSLSocket;
|
||||
*/
|
||||
public class LanLinkProvider extends BaseLinkProvider implements LanLink.LinkDisconnectedCallback {
|
||||
|
||||
public static final int MIN_VERSION_WITH_SSL_SUPPORT = 6;
|
||||
private static final int MIN_VERSION_WITH_NEW_PORT_SUPPORT = 7;
|
||||
|
||||
private final static int MIN_PORT = 1716;
|
||||
private final static int MAX_PORT = 1764;
|
||||
final static int PAYLOAD_TRANSFER_MIN_PORT = 1739;
|
||||
@ -93,7 +90,7 @@ public class LanLinkProvider extends BaseLinkProvider implements LanLink.LinkDis
|
||||
}
|
||||
|
||||
//They received my UDP broadcast and are connecting to me. The first thing they sned should be their identity.
|
||||
private void tcpPacketReceived(Socket socket) throws Exception {
|
||||
private void tcpPacketReceived(Socket socket) {
|
||||
|
||||
NetworkPacket networkPacket;
|
||||
try {
|
||||
@ -116,7 +113,7 @@ public class LanLinkProvider extends BaseLinkProvider implements LanLink.LinkDis
|
||||
}
|
||||
|
||||
//I've received their broadcast and should connect to their TCP socket and send my identity.
|
||||
private void udpPacketReceived(DatagramPacket packet) throws Exception {
|
||||
private void udpPacketReceived(DatagramPacket packet) {
|
||||
|
||||
final InetAddress address = packet.getAddress();
|
||||
|
||||
@ -136,11 +133,6 @@ public class LanLinkProvider extends BaseLinkProvider implements LanLink.LinkDis
|
||||
}
|
||||
}
|
||||
|
||||
if (identityPacket.getInt("protocolVersion") >= MIN_VERSION_WITH_NEW_PORT_SUPPORT && identityPacket.getInt("tcpPort") < MIN_PORT) {
|
||||
Log.w("KDE/LanLinkProvider", "Ignoring a udp broadcast from legacy port because it comes from a device which knows about the new port.");
|
||||
return;
|
||||
}
|
||||
|
||||
Log.i("KDE/LanLinkProvider", "Broadcast identity package received from " + identityPacket.getString("deviceName"));
|
||||
|
||||
int tcpPort = identityPacket.getInt("tcpPort", MIN_PORT);
|
||||
@ -206,61 +198,56 @@ public class LanLinkProvider extends BaseLinkProvider implements LanLink.LinkDis
|
||||
// If I'm the TCP server I will be the SSL client and viceversa.
|
||||
final boolean clientMode = (connectionStarted == LanLink.ConnectionStarted.Locally);
|
||||
|
||||
// Add ssl handler if device uses new protocol
|
||||
// Do the SSL handshake
|
||||
try {
|
||||
if (identityPacket.getInt("protocolVersion") >= MIN_VERSION_WITH_SSL_SUPPORT) {
|
||||
SharedPreferences preferences = context.getSharedPreferences("trusted_devices", Context.MODE_PRIVATE);
|
||||
boolean isDeviceTrusted = preferences.getBoolean(deviceId, false);
|
||||
|
||||
SharedPreferences preferences = context.getSharedPreferences("trusted_devices", Context.MODE_PRIVATE);
|
||||
boolean isDeviceTrusted = preferences.getBoolean(deviceId, false);
|
||||
if (isDeviceTrusted && !SslHelper.isCertificateStored(context, deviceId)) {
|
||||
//Device paired with and old version, we can't use it as we lack the certificate
|
||||
BackgroundService.RunCommand(context, service -> {
|
||||
Device device = service.getDevice(deviceId);
|
||||
if (device == null) return;
|
||||
device.unpair();
|
||||
//Retry as unpaired
|
||||
identityPacketReceived(identityPacket, socket, connectionStarted);
|
||||
});
|
||||
}
|
||||
|
||||
if (isDeviceTrusted && !SslHelper.isCertificateStored(context, deviceId)) {
|
||||
//Device paired with and old version, we can't use it as we lack the certificate
|
||||
Log.i("KDE/LanLinkProvider", "Starting SSL handshake with " + identityPacket.getString("deviceName") + " trusted:" + isDeviceTrusted);
|
||||
|
||||
final SSLSocket sslsocket = SslHelper.convertToSslSocket(context, socket, deviceId, isDeviceTrusted, clientMode);
|
||||
sslsocket.addHandshakeCompletedListener(event -> {
|
||||
String mode = clientMode ? "client" : "server";
|
||||
try {
|
||||
Certificate certificate = event.getPeerCertificates()[0];
|
||||
identityPacket.set("certificate", Base64.encodeToString(certificate.getEncoded(), 0));
|
||||
Log.i("KDE/LanLinkProvider", "Handshake as " + mode + " successful with " + identityPacket.getString("deviceName") + " secured with " + event.getCipherSuite());
|
||||
addLink(identityPacket, sslsocket, connectionStarted);
|
||||
} catch (Exception e) {
|
||||
Log.e("KDE/LanLinkProvider", "Handshake as " + mode + " failed with " + identityPacket.getString("deviceName"), e);
|
||||
BackgroundService.RunCommand(context, service -> {
|
||||
Device device = service.getDevice(deviceId);
|
||||
if (device == null) return;
|
||||
device.unpair();
|
||||
//Retry as unpaired
|
||||
identityPacketReceived(identityPacket, socket, connectionStarted);
|
||||
});
|
||||
}
|
||||
|
||||
Log.i("KDE/LanLinkProvider", "Starting SSL handshake with " + identityPacket.getString("deviceName") + " trusted:" + isDeviceTrusted);
|
||||
|
||||
final SSLSocket sslsocket = SslHelper.convertToSslSocket(context, socket, deviceId, isDeviceTrusted, clientMode);
|
||||
sslsocket.addHandshakeCompletedListener(event -> {
|
||||
String mode = clientMode ? "client" : "server";
|
||||
try {
|
||||
Certificate certificate = event.getPeerCertificates()[0];
|
||||
identityPacket.set("certificate", Base64.encodeToString(certificate.getEncoded(), 0));
|
||||
Log.i("KDE/LanLinkProvider", "Handshake as " + mode + " successful with " + identityPacket.getString("deviceName") + " secured with " + event.getCipherSuite());
|
||||
addLink(identityPacket, sslsocket, connectionStarted);
|
||||
} catch (Exception e) {
|
||||
Log.e("KDE/LanLinkProvider", "Handshake as " + mode + " failed with " + identityPacket.getString("deviceName"), e);
|
||||
BackgroundService.RunCommand(context, service -> {
|
||||
Device device = service.getDevice(deviceId);
|
||||
if (device == null) return;
|
||||
device.unpair();
|
||||
});
|
||||
});
|
||||
//Handshake is blocking, so do it on another thread and free this thread to keep receiving new connection
|
||||
new Thread(() -> {
|
||||
try {
|
||||
synchronized (this) {
|
||||
sslsocket.startHandshake();
|
||||
}
|
||||
});
|
||||
//Handshake is blocking, so do it on another thread and free this thread to keep receiving new connection
|
||||
new Thread(() -> {
|
||||
try {
|
||||
synchronized (this) {
|
||||
sslsocket.startHandshake();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e("KDE/LanLinkProvider", "Handshake failed with " + identityPacket.getString("deviceName"), e);
|
||||
} catch (Exception e) {
|
||||
Log.e("KDE/LanLinkProvider", "Handshake failed with " + identityPacket.getString("deviceName"), e);
|
||||
|
||||
//String[] ciphers = sslsocket.getSupportedCipherSuites();
|
||||
//for (String cipher : ciphers) {
|
||||
// Log.i("SupportedCiphers","cipher: " + cipher);
|
||||
//}
|
||||
}
|
||||
}).start();
|
||||
} else {
|
||||
addLink(identityPacket, socket, connectionStarted);
|
||||
}
|
||||
//String[] ciphers = sslsocket.getSupportedCipherSuites();
|
||||
//for (String cipher : ciphers) {
|
||||
// Log.i("SupportedCiphers","cipher: " + cipher);
|
||||
//}
|
||||
}
|
||||
}).start();
|
||||
} catch (Exception e) {
|
||||
Log.e("LanLink", "Exception", e);
|
||||
}
|
||||
@ -280,7 +267,7 @@ public class LanLinkProvider extends BaseLinkProvider implements LanLink.LinkDis
|
||||
* @param connectionOrigin which side started this connection
|
||||
* @throws IOException if an exception is thrown by {@link LanLink#reset(Socket, LanLink.ConnectionStarted)}
|
||||
*/
|
||||
private void addLink(final NetworkPacket identityPacket, Socket socket, LanLink.ConnectionStarted connectionOrigin) throws IOException {
|
||||
private void addLink(final NetworkPacket identityPacket, SSLSocket socket, LanLink.ConnectionStarted connectionOrigin) throws IOException {
|
||||
|
||||
String deviceId = identityPacket.getString("deviceId");
|
||||
LanLink currentLink = visibleComputers.get(deviceId);
|
||||
|
@ -22,7 +22,6 @@ package org.kde.kdeconnect.Backends.LanBackend;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
|
||||
@ -31,9 +30,7 @@ import org.kde.kdeconnect.Device;
|
||||
import org.kde.kdeconnect.NetworkPacket;
|
||||
import org.kde.kdeconnect_tp.R;
|
||||
|
||||
import java.security.KeyFactory;
|
||||
import java.security.cert.CertificateEncodingException;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
@ -54,14 +51,11 @@ public class LanPairingHandler extends BasePairingHandler {
|
||||
private NetworkPacket createPairPacket() {
|
||||
NetworkPacket np = new NetworkPacket(NetworkPacket.PACKET_TYPE_PAIR);
|
||||
np.set("pair", true);
|
||||
SharedPreferences globalSettings = PreferenceManager.getDefaultSharedPreferences(mDevice.getContext());
|
||||
String publicKey = "-----BEGIN PUBLIC KEY-----\n" + globalSettings.getString("publicKey", "").trim()+ "\n-----END PUBLIC KEY-----\n";
|
||||
np.set("publicKey", publicKey);
|
||||
return np;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void packageReceived(NetworkPacket np) throws Exception{
|
||||
public void packageReceived(NetworkPacket np) {
|
||||
|
||||
boolean wantsPair = np.getBoolean("pair");
|
||||
|
||||
@ -77,15 +71,6 @@ public class LanPairingHandler extends BasePairingHandler {
|
||||
|
||||
if (wantsPair) {
|
||||
|
||||
//Retrieve their public key
|
||||
try {
|
||||
String publicKeyContent = np.getString("publicKey").replace("-----BEGIN PUBLIC KEY-----\n","").replace("-----END PUBLIC KEY-----\n", "");
|
||||
byte[] publicKeyBytes = Base64.decode(publicKeyContent, 0);
|
||||
mDevice.publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(publicKeyBytes));
|
||||
} catch (Exception e) {
|
||||
//IGNORE
|
||||
}
|
||||
|
||||
if (mPairStatus == PairStatus.Requested) { //We started pairing
|
||||
|
||||
hidePairingNotification();
|
||||
@ -204,15 +189,6 @@ public class LanPairingHandler extends BasePairingHandler {
|
||||
//Log.e("KDE/PairingDone", "Pairing Done");
|
||||
SharedPreferences.Editor editor = mDevice.getContext().getSharedPreferences(mDevice.getDeviceId(), Context.MODE_PRIVATE).edit();
|
||||
|
||||
if (mDevice.publicKey != null) {
|
||||
try {
|
||||
String encodedPublicKey = Base64.encodeToString(mDevice.publicKey.getEncoded(), 0);
|
||||
editor.putString("publicKey", encodedPublicKey);
|
||||
} catch (Exception e) {
|
||||
Log.e("KDE/PairingDone", "Error encoding public key", e);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
String encodedCertificate = Base64.encodeToString(mDevice.certificate.getEncoded(), 0);
|
||||
editor.putString("certificate", encodedCertificate);
|
||||
|
@ -28,8 +28,6 @@ import org.kde.kdeconnect.Backends.BasePairingHandler;
|
||||
import org.kde.kdeconnect.Device;
|
||||
import org.kde.kdeconnect.NetworkPacket;
|
||||
|
||||
import java.security.PublicKey;
|
||||
|
||||
public class LoopbackLink extends BaseLink {
|
||||
|
||||
public LoopbackLink(Context context, BaseLinkProvider linkProvider) {
|
||||
@ -58,8 +56,4 @@ public class LoopbackLink extends BaseLink {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendPacketEncrypted(NetworkPacket np, Device.SendPacketStatusCallback callback, PublicKey key) {
|
||||
return sendPacket(np, callback);
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ public class LoopbackPairingHandler extends BasePairingHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void packageReceived(NetworkPacket np) throws Exception {
|
||||
public void packageReceived(NetworkPacket np) {
|
||||
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,6 @@ import android.util.Log;
|
||||
|
||||
import org.kde.kdeconnect.Backends.BaseLink;
|
||||
import org.kde.kdeconnect.Backends.BasePairingHandler;
|
||||
import org.kde.kdeconnect.Backends.LanBackend.LanLinkProvider;
|
||||
import org.kde.kdeconnect.Helpers.NotificationHelper;
|
||||
import org.kde.kdeconnect.Helpers.SecurityHelpers.SslHelper;
|
||||
import org.kde.kdeconnect.Plugins.Plugin;
|
||||
@ -45,10 +44,8 @@ import org.kde.kdeconnect_tp.R;
|
||||
|
||||
import java.security.KeyFactory;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
@ -68,7 +65,6 @@ public class Device implements BaseLink.PacketReceiver {
|
||||
|
||||
private final String deviceId;
|
||||
private String name;
|
||||
public PublicKey publicKey;
|
||||
public Certificate certificate;
|
||||
private int notificationId;
|
||||
private int protocolVersion;
|
||||
@ -150,16 +146,6 @@ public class Device implements BaseLink.PacketReceiver {
|
||||
this.protocolVersion = NetworkPacket.ProtocolVersion; //We don't know it yet
|
||||
this.deviceType = DeviceType.FromString(settings.getString("deviceType", "desktop"));
|
||||
|
||||
try {
|
||||
String publicKeyStr = settings.getString("publicKey", null);
|
||||
if (publicKeyStr != null) {
|
||||
byte[] publicKeyBytes = Base64.decode(publicKeyStr, 0);
|
||||
publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(publicKeyBytes));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e("KDE/Device", "Exception deserializing stored public key for device", e);
|
||||
}
|
||||
|
||||
//Assume every plugin is supported until addLink is called and we can get the actual list
|
||||
m_supportedPlugins = new Vector<>(PluginFactory.getAvailablePlugins());
|
||||
|
||||
@ -178,7 +164,6 @@ public class Device implements BaseLink.PacketReceiver {
|
||||
this.pairStatus = PairStatus.NotPaired;
|
||||
this.protocolVersion = 0;
|
||||
this.deviceType = DeviceType.Computer;
|
||||
this.publicKey = null;
|
||||
|
||||
settings = context.getSharedPreferences(deviceId, Context.MODE_PRIVATE);
|
||||
|
||||
@ -546,8 +531,6 @@ public class Device implements BaseLink.PacketReceiver {
|
||||
@Override
|
||||
public void onPacketReceived(NetworkPacket np) {
|
||||
|
||||
hackToMakeRetrocompatiblePacketTypes(np);
|
||||
|
||||
if (NetworkPacket.PACKET_TYPE_PAIR.equals(np.getType())) {
|
||||
|
||||
Log.i("KDE/Device", "Pair package");
|
||||
@ -651,20 +634,12 @@ public class Device implements BaseLink.PacketReceiver {
|
||||
}
|
||||
*/
|
||||
|
||||
hackToMakeRetrocompatiblePacketTypes(np);
|
||||
|
||||
boolean useEncryption = (protocolVersion < LanLinkProvider.MIN_VERSION_WITH_SSL_SUPPORT && (!np.getType().equals(NetworkPacket.PACKET_TYPE_PAIR) && isPaired()));
|
||||
|
||||
boolean success = false;
|
||||
//Make a copy to avoid concurrent modification exception if the original list changes
|
||||
for (final BaseLink link : links) {
|
||||
if (link == null)
|
||||
continue; //Since we made a copy, maybe somebody destroyed the link in the meanwhile
|
||||
if (useEncryption) {
|
||||
success = link.sendPacketEncrypted(np, callback, publicKey);
|
||||
} else {
|
||||
success = link.sendPacket(np, callback);
|
||||
}
|
||||
success = link.sendPacket(np, callback);
|
||||
if (success) break; //If the link didn't call sendSuccess(), try the next one
|
||||
}
|
||||
|
||||
@ -796,7 +771,6 @@ public class Device implements BaseLink.PacketReceiver {
|
||||
boolean success = addPlugin(pluginKey);
|
||||
if (success) {
|
||||
for (String packageType : pluginInfo.getSupportedPacketTypes()) {
|
||||
packageType = hackToMakeRetrocompatiblePacketTypes(packageType);
|
||||
ArrayList<String> plugins = newPluginsByIncomingInterface.get(packageType);
|
||||
if (plugins == null) plugins = new ArrayList<>();
|
||||
plugins.add(pluginKey);
|
||||
@ -866,14 +840,4 @@ public class Device implements BaseLink.PacketReceiver {
|
||||
return m_supportedPlugins;
|
||||
}
|
||||
|
||||
private void hackToMakeRetrocompatiblePacketTypes(NetworkPacket np) {
|
||||
if (protocolVersion >= 6) return;
|
||||
np.mType = np.getType().replace(".request", "");
|
||||
}
|
||||
|
||||
private String hackToMakeRetrocompatiblePacketTypes(String type) {
|
||||
if (protocolVersion >= 6) return type;
|
||||
return type.replace(".request", "");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -26,11 +26,6 @@ import android.preference.PreferenceManager;
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.kde.kdeconnect.NetworkPacket;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.KeyPair;
|
||||
@ -40,8 +35,6 @@ import java.security.PublicKey;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
|
||||
public class RsaHelper {
|
||||
|
||||
public static void initialiseRsaKeys(Context context) {
|
||||
@ -77,67 +70,12 @@ public class RsaHelper {
|
||||
return KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(publicKeyBytes));
|
||||
}
|
||||
|
||||
public static PublicKey getPublicKey(Context context, String deviceId) throws GeneralSecurityException {
|
||||
SharedPreferences settings = context.getSharedPreferences(deviceId, Context.MODE_PRIVATE);
|
||||
byte[] publicKeyBytes = Base64.decode(settings.getString("publicKey", ""), 0);
|
||||
return KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(publicKeyBytes));
|
||||
}
|
||||
|
||||
public static PrivateKey getPrivateKey(Context context) throws GeneralSecurityException {
|
||||
SharedPreferences globalSettings = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
byte[] privateKeyBytes = Base64.decode(globalSettings.getString("privateKey", ""), 0);
|
||||
return KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(privateKeyBytes));
|
||||
}
|
||||
|
||||
public static NetworkPacket encrypt(NetworkPacket np, PublicKey publicKey) throws GeneralSecurityException, JSONException {
|
||||
|
||||
String serialized = np.serialize();
|
||||
|
||||
int chunkSize = 128;
|
||||
|
||||
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
||||
|
||||
JSONArray chunks = new JSONArray();
|
||||
while (serialized.length() > 0) {
|
||||
if (serialized.length() < chunkSize) {
|
||||
chunkSize = serialized.length();
|
||||
}
|
||||
String chunk = serialized.substring(0, chunkSize);
|
||||
serialized = serialized.substring(chunkSize);
|
||||
byte[] chunkBytes = chunk.getBytes(Charset.defaultCharset());
|
||||
byte[] encryptedChunk;
|
||||
encryptedChunk = cipher.doFinal(chunkBytes);
|
||||
chunks.put(Base64.encodeToString(encryptedChunk, Base64.NO_WRAP));
|
||||
}
|
||||
|
||||
//Log.i("NetworkPacket", "Encrypted " + chunks.length()+" chunks");
|
||||
|
||||
NetworkPacket encrypted = new NetworkPacket(NetworkPacket.PACKET_TYPE_ENCRYPTED);
|
||||
encrypted.set("data", chunks);
|
||||
encrypted.setPayload(np.getPayload());
|
||||
return encrypted;
|
||||
|
||||
}
|
||||
|
||||
public static NetworkPacket decrypt(NetworkPacket np, PrivateKey privateKey) throws GeneralSecurityException, JSONException {
|
||||
|
||||
JSONArray chunks = np.getJSONArray("data");
|
||||
|
||||
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING");
|
||||
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
||||
|
||||
StringBuilder decryptedJson = new StringBuilder();
|
||||
for (int i = 0; i < chunks.length(); i++) {
|
||||
byte[] encryptedChunk = Base64.decode(chunks.getString(i), Base64.NO_WRAP);
|
||||
String decryptedChunk = new String(cipher.doFinal(encryptedChunk));
|
||||
decryptedJson.append(decryptedChunk);
|
||||
}
|
||||
|
||||
NetworkPacket decrypted = NetworkPacket.unserialize(decryptedJson.toString());
|
||||
decrypted.setPayload(np.getPayload());
|
||||
return decrypted;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -65,11 +65,6 @@ import javax.net.ssl.X509TrustManager;
|
||||
|
||||
public class SslHelper {
|
||||
|
||||
public enum SslMode {
|
||||
Client,
|
||||
Server
|
||||
}
|
||||
|
||||
public static X509Certificate certificate; //my device's certificate
|
||||
|
||||
public static final BouncyCastleProvider BC = new BouncyCastleProvider();
|
||||
|
@ -44,12 +44,10 @@ public class NetworkPacket {
|
||||
|
||||
public final static String PACKET_TYPE_IDENTITY = "kdeconnect.identity";
|
||||
public final static String PACKET_TYPE_PAIR = "kdeconnect.pair";
|
||||
public final static String PACKET_TYPE_ENCRYPTED = "kdeconnect.encrypted";
|
||||
|
||||
public static Set<String> protocolPacketTypes = new HashSet<String>() {{
|
||||
add(PACKET_TYPE_IDENTITY);
|
||||
add(PACKET_TYPE_PAIR);
|
||||
add(PACKET_TYPE_ENCRYPTED);
|
||||
}};
|
||||
|
||||
private long mId;
|
||||
|
@ -25,7 +25,6 @@ import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.widget.Button;
|
||||
|
||||
import org.kde.kdeconnect.Device;
|
||||
import org.kde.kdeconnect.NetworkPacket;
|
||||
@ -185,21 +184,6 @@ public abstract class Plugin {
|
||||
*/
|
||||
public abstract String[] getOutgoingPacketTypes();
|
||||
|
||||
/**
|
||||
* Creates a button that will be displayed in the user interface
|
||||
* It can open an activity or perform any other action that the
|
||||
* plugin would wants to expose to the user. Return null if no
|
||||
* button should be displayed.
|
||||
*/
|
||||
@Deprecated
|
||||
public Button getInterfaceButton(final Activity activity) {
|
||||
if (!hasMainActivity()) return null;
|
||||
Button b = new Button(activity);
|
||||
b.setText(getActionName());
|
||||
b.setOnClickListener(view -> startMainActivity(activity));
|
||||
return b;
|
||||
}
|
||||
|
||||
protected String[] getRequiredPermissions() {
|
||||
return new String[0];
|
||||
}
|
||||
|
@ -310,7 +310,7 @@ public class AndroidSafSshFile implements SshFile {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Attribute, Object> getAttributes(boolean followLinks) throws IOException {
|
||||
public Map<Attribute, Object> getAttributes(boolean followLinks) {
|
||||
Map<SshFile.Attribute, Object> attributes = new HashMap<>();
|
||||
for (SshFile.Attribute attr : SshFile.Attribute.values()) {
|
||||
switch (attr) {
|
||||
|
@ -53,7 +53,7 @@ class RootFile implements SshFile {
|
||||
return "/";
|
||||
}
|
||||
|
||||
public Map<Attribute, Object> getAttributes(boolean followLinks) throws IOException {
|
||||
public Map<Attribute, Object> getAttributes(boolean followLinks) {
|
||||
Map<Attribute, Object> attrs = new HashMap<>();
|
||||
|
||||
attrs.put(Attribute.Size, 0);
|
||||
|
@ -95,11 +95,8 @@ class SimpleSftpServer {
|
||||
sshd.setCommandFactory(new ScpCommandFactory());
|
||||
sshd.setSubsystemFactories(Collections.singletonList(new SftpSubsystem.Factory()));
|
||||
|
||||
if (device.publicKey != null) {
|
||||
keyAuth.deviceKey = device.publicKey;
|
||||
} else {
|
||||
keyAuth.deviceKey = device.certificate.getPublicKey();
|
||||
}
|
||||
keyAuth.deviceKey = device.certificate.getPublicKey();
|
||||
|
||||
sshd.setPublickeyAuthenticator(keyAuth);
|
||||
sshd.setPasswordAuthenticator(passwordAuth);
|
||||
}
|
||||
|
@ -195,7 +195,7 @@ public class DeviceTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPairingDoneWithCertificate() throws Exception {
|
||||
public void testPairingDoneWithCertificate() {
|
||||
KeyPair keyPair = null;
|
||||
try {
|
||||
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
|
||||
|
@ -43,6 +43,8 @@ import java.io.OutputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
|
||||
import javax.net.ssl.SSLSocket;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@RunWith(PowerMockRunner.class)
|
||||
@ -71,11 +73,11 @@ public class LanLinkTest {
|
||||
Mockito.doThrow(new IOException("AAA")).when(badOutputStream).write(Mockito.any(byte[].class));
|
||||
|
||||
|
||||
Socket socketMock = Mockito.mock(Socket.class);
|
||||
SSLSocket socketMock = Mockito.mock(SSLSocket.class);
|
||||
Mockito.when(socketMock.getRemoteSocketAddress()).thenReturn(new InetSocketAddress(5000));
|
||||
Mockito.when(socketMock.getOutputStream()).thenReturn(goodOutputStream);
|
||||
|
||||
Socket socketBadMock = Mockito.mock(Socket.class);
|
||||
SSLSocket socketBadMock = Mockito.mock(SSLSocket.class);
|
||||
Mockito.when(socketBadMock.getRemoteSocketAddress()).thenReturn(new InetSocketAddress(5000));
|
||||
Mockito.when(socketBadMock.getOutputStream()).thenReturn(badOutputStream);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user