diff --git a/src/org/kde/kdeconnect/Backends/LanBackend/LanLink.java b/src/org/kde/kdeconnect/Backends/LanBackend/LanLink.java index d1e41c7c..44e956ac 100644 --- a/src/org/kde/kdeconnect/Backends/LanBackend/LanLink.java +++ b/src/org/kde/kdeconnect/Backends/LanBackend/LanLink.java @@ -196,7 +196,6 @@ public class LanLink extends BaseLink { InetSocketAddress address = (InetSocketAddress)channel.remoteAddress(); socket.connect(new InetSocketAddress(address.getAddress(), tcpPort)); np.setPayload(socket.getInputStream(), np.getPayloadSize()); - Log.e("KDE/LanLink", "Has payload "); } catch (Exception e) { try { socket.close(); } catch(Exception ignored) { } e.printStackTrace(); @@ -208,8 +207,8 @@ public class LanLink extends BaseLink { packageReceived(np); } - static ServerSocket openTcpSocketOnFreePort(Context context, String deviceId, boolean onSsl) throws IOException { - if (onSsl) { + static ServerSocket openTcpSocketOnFreePort(Context context, String deviceId, boolean useSsl) throws IOException { + if (useSsl) { return openSecureServerSocket(context, deviceId); } else { return openUnsecureSocketOnFreePort(); diff --git a/src/org/kde/kdeconnect/Backends/LanBackend/LanLinkProvider.java b/src/org/kde/kdeconnect/Backends/LanBackend/LanLinkProvider.java index d17f4bca..4ac83040 100644 --- a/src/org/kde/kdeconnect/Backends/LanBackend/LanLinkProvider.java +++ b/src/org/kde/kdeconnect/Backends/LanBackend/LanLinkProvider.java @@ -85,17 +85,12 @@ public class LanLinkProvider extends BaseLinkProvider { @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); - // TODO : Add necessary action on ssl handshake failure - } - - @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { - Log.e("KDE/LanLinkProvider", "Channel Active : " + ctx.channel().hashCode()); + // If certificate changed, getting SocketException, connection reset by peer + // Ssl engines closes by itself, so do channel and link is removed } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { - Log.e("KDE/LanLinkProvider", "Channel In active :" + ctx.channel().hashCode()); try { long id = ctx.channel().hashCode(); final LanLink brokenLink = nioLinks.get(id); @@ -131,9 +126,9 @@ public class LanLinkProvider extends BaseLinkProvider { }).start(); } - } catch (Exception e) { //If we don't catch it here, Mina will swallow it :/ + } catch (Exception e) { e.printStackTrace(); - Log.e("KDE/LanLinkProvider", "sessionClosed exception"); + Log.e("KDE/LanLinkProvider", "channelInactive exception"); } } @@ -150,7 +145,6 @@ public class LanLinkProvider extends BaseLinkProvider { } final NetworkPackage np = NetworkPackage.unserialize(theMessage); - Log.e("KDE/LanLinkProvider", theMessage); if (np.getType().equals(NetworkPackage.PACKAGE_TYPE_IDENTITY)) { @@ -165,8 +159,7 @@ public class LanLinkProvider extends BaseLinkProvider { nioLinks.put(ctx.channel().hashCode(), link); //Log.i("KDE/LanLinkProvider","nioLinks.size(): " + nioLinks.size()); - // Check if ssl supported, and add ssl handler - // Sslengine is returning null in some cases + // Check if ssl supported on other device and enabled on my device, and add ssl handler try { if (myIdentityPackage.getBoolean("sslSupported") && np.getBoolean("sslSupported", false)) { Log.e("KDE/LanLinkProvider", "Remote device " + np.getString("deviceName") + " supports ssl"); @@ -190,7 +183,7 @@ public class LanLinkProvider extends BaseLinkProvider { } } catch (Exception e) { e.printStackTrace(); - addLink(np, link); // If error in ssl engine, which is returning null in some cases + addLink(np, link); // If exception getting ssl engine } } else { @@ -211,7 +204,6 @@ public class LanLinkProvider extends BaseLinkProvider { protected void channelRead0(final ChannelHandlerContext ctx, DatagramPacket packet) throws Exception { try { String theMessage = packet.content().toString(CharsetUtil.UTF_8); - Log.e("KDE/LanLinkProvider", "Udp message received : " + theMessage); final NetworkPackage identityPackage = NetworkPackage.unserialize(theMessage); @@ -221,7 +213,6 @@ public class LanLinkProvider extends BaseLinkProvider { } else { String myId = NetworkPackage.createIdentityPackage(context).getString("deviceId"); if (identityPackage.getString("deviceId").equals(myId)) { - Log.e("KDE/LanLinkProvider", "Oh, its my identity package"); return; } } diff --git a/src/org/kde/kdeconnect/Device.java b/src/org/kde/kdeconnect/Device.java index 0dc285a1..7424f117 100644 --- a/src/org/kde/kdeconnect/Device.java +++ b/src/org/kde/kdeconnect/Device.java @@ -28,7 +28,6 @@ import android.content.Intent; import android.content.SharedPreferences; import android.content.res.Resources; import android.graphics.drawable.Drawable; -import android.os.Build; import android.os.Handler; import android.os.Looper; import android.preference.PreferenceManager; @@ -305,17 +304,19 @@ public class Device implements BaseLink.PackageReceiver { preferences.edit().putBoolean(deviceId,true).apply(); //Store device information needed to create a Device object in a future + SharedPreferences.Editor editor = settings.edit(); try { - SharedPreferences.Editor editor = settings.edit(); editor.putString("deviceName", getName()); editor.putString("deviceType", deviceType.toString()); String encodedPublicKey = Base64.encodeToString(publicKey.getEncoded(), 0); editor.putString("publicKey", encodedPublicKey); String encodedCertificate = Base64.encodeToString(certificate.getEncoded(), 0); editor.putString("certificate", encodedCertificate); - editor.apply(); } catch (Exception e){ + Log.e("KDE/Device", "Exception pairing done"); e.printStackTrace(); + } finally { + editor.apply(); } reloadPluginsFromSettings(); diff --git a/src/org/kde/kdeconnect/Helpers/SecurityHelpers/SslHelper.java b/src/org/kde/kdeconnect/Helpers/SecurityHelpers/SslHelper.java index af39ef00..f972fbb3 100644 --- a/src/org/kde/kdeconnect/Helpers/SecurityHelpers/SslHelper.java +++ b/src/org/kde/kdeconnect/Helpers/SecurityHelpers/SslHelper.java @@ -26,7 +26,6 @@ import android.preference.PreferenceManager; import android.util.Base64; import android.util.Log; -import org.apache.mina.filter.ssl.SslFilter; import org.bouncycastle.asn1.x500.X500NameBuilder; import org.bouncycastle.asn1.x500.style.BCStyle; import org.bouncycastle.cert.X509CertificateHolder; @@ -45,7 +44,6 @@ import java.security.SecureRandom; import java.security.cert.X509Certificate; import java.util.Date; -import javax.net.ssl.KeyManager; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; @@ -53,9 +51,6 @@ import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509TrustManager; -import io.netty.handler.ssl.SslContext; - - public class SslHelper { public enum SslMode{ @@ -214,70 +209,4 @@ public class SslHelper { } return null; } - - // TODO : Remove this method, and use the above one, since it trusts all certificates - public static SslFilter getTrustAllCertsFilter(Context context, SslMode sslMode){ - try{ - - // Get device private key - PrivateKey privateKey = RsaHelper.getPrivateKey(context); - - // Get my certificate - SharedPreferences globalSettings = PreferenceManager.getDefaultSharedPreferences(context); - byte[] myCertificateBytes = Base64.decode(globalSettings.getString("certificate", ""), 0); - X509CertificateHolder myCertificateHolder = new X509CertificateHolder(myCertificateBytes); - X509Certificate myCertificate = new JcaX509CertificateConverter().setProvider(new BouncyCastleProvider()).getCertificate(myCertificateHolder); - - - // Setup keystore - KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); - keyStore.load(null, null); - keyStore.setKeyEntry("key", privateKey, "".toCharArray(), new java.security.cert.Certificate[]{myCertificate});; - - // Setup key manager factory - KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); - keyManagerFactory.init(keyStore, "".toCharArray()); - - - // Setup default trust manager - TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); - trustManagerFactory.init(keyStore); - - // Setup custom trust manager if device not trusted - TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() { - public java.security.cert.X509Certificate[] getAcceptedIssuers() { - return new X509Certificate[0]; - } - - @Override - public void checkClientTrusted(X509Certificate[] certs, String authType) { - } - - @Override - public void checkServerTrusted(X509Certificate[] certs, String authType) { - } - - } - }; - - // TODO : if device trusted, set need client auth - - SSLContext tlsContext = SSLContext.getInstance("TLS"); - tlsContext.init(keyManagerFactory.getKeyManagers(), trustAllCerts, new SecureRandom()); - SslFilter filter = new SslFilter(tlsContext,true); - - if (sslMode == SslMode.Client){ - filter.setUseClientMode(true); - }else{ - filter.setUseClientMode(false); - filter.setWantClientAuth(true); - } - - return filter; - }catch (Exception e){ - e.printStackTrace(); - Log.e("SslHelper", "Error creating ssl filter"); - } - return null; - } } diff --git a/src/org/kde/kdeconnect/UserInterface/PairActivity.java b/src/org/kde/kdeconnect/UserInterface/PairActivity.java index 39e23b2c..3aba436f 100644 --- a/src/org/kde/kdeconnect/UserInterface/PairActivity.java +++ b/src/org/kde/kdeconnect/UserInterface/PairActivity.java @@ -25,11 +25,9 @@ import android.content.Context; import android.os.Bundle; import android.support.v7.app.ActionBar; import android.support.v7.app.ActionBarActivity; -import android.util.Base64; import android.util.Log; import android.view.View; import android.widget.Button; -import android.widget.LinearLayout; import android.widget.TextView; import org.kde.kdeconnect.BackgroundService; @@ -145,7 +143,6 @@ public class PairActivity extends ActionBarActivity { public void onClick(View view) { pairButton.setVisibility(View.GONE); ((TextView) findViewById(R.id.pair_message)).setText(""); - findViewById(R.id.secret_keys).setVisibility(View.GONE); findViewById(R.id.pair_progress).setVisibility(View.VISIBLE); BackgroundService.RunCommand(PairActivity.this, new BackgroundService.InstanceCallback() { @Override diff --git a/tests/org/kde/kdeconnect/DeviceTest.java b/tests/org/kde/kdeconnect/DeviceTest.java index 5d3383db..60111fd6 100644 --- a/tests/org/kde/kdeconnect/DeviceTest.java +++ b/tests/org/kde/kdeconnect/DeviceTest.java @@ -26,13 +26,24 @@ import android.test.AndroidTestCase; import android.util.Base64; import android.util.Log; +import org.bouncycastle.asn1.x500.X500NameBuilder; +import org.bouncycastle.asn1.x500.style.BCStyle; +import org.bouncycastle.cert.X509v3CertificateBuilder; +import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; +import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.operator.ContentSigner; +import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; import org.kde.kdeconnect.Backends.LanBackend.LanLink; import org.kde.kdeconnect.Backends.LanBackend.LanLinkProvider; import org.mockito.Mockito; import java.lang.reflect.Method; +import java.math.BigInteger; import java.security.KeyPair; import java.security.KeyPairGenerator; +import java.security.cert.X509Certificate; +import java.util.Date; public class DeviceTest extends AndroidTestCase { @@ -140,6 +151,8 @@ public class DeviceTest extends AndroidTestCase { assertEquals(device.getDeviceId(), "unpairedTestDevice"); assertEquals(device.getName(), "Unpaired Test Device"); assertEquals(device.getDeviceType(), Device.DeviceType.Phone); + assertNotNull(device.publicKey); + assertNull(device.certificate); Method method; try { @@ -166,6 +179,90 @@ public class DeviceTest extends AndroidTestCase { } + public void testPairingDoneWithCertificate() throws Exception{ + KeyPair keyPair = null; + try { + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); + keyGen.initialize(2048); + keyPair = keyGen.genKeyPair(); + } catch(Exception e) { + e.printStackTrace(); + Log.e("KDE/initializeRsaKeys", "Exception"); + } + + X509Certificate certificate = null; + try { + + BouncyCastleProvider BC = new BouncyCastleProvider(); + + X500NameBuilder nameBuilder = new X500NameBuilder(BCStyle.INSTANCE); + nameBuilder.addRDN(BCStyle.CN, "testDevice"); + nameBuilder.addRDN(BCStyle.OU, "KDE Connect"); + nameBuilder.addRDN(BCStyle.O, "KDE"); + Date notBefore = new Date(System.currentTimeMillis()); + Date notAfter = new Date(System.currentTimeMillis() + System.currentTimeMillis()); + X509v3CertificateBuilder certificateBuilder = new JcaX509v3CertificateBuilder( + nameBuilder.build(), + BigInteger.ONE, + notBefore, + notAfter, + nameBuilder.build(), + keyPair.getPublic() + ); + ContentSigner contentSigner = new JcaContentSignerBuilder("SHA256WithRSAEncryption").setProvider(BC).build(keyPair.getPrivate()); + certificate = new JcaX509CertificateConverter().setProvider(BC).getCertificate(certificateBuilder.build(contentSigner)); + + } catch(Exception e) { + e.printStackTrace(); + Log.e("KDE/initialiseCertificate", "Exception"); + } + + NetworkPackage fakeNetworkPackage = new NetworkPackage(NetworkPackage.PACKAGE_TYPE_IDENTITY); + fakeNetworkPackage.set("deviceId", "unpairedTestDevice"); + fakeNetworkPackage.set("deviceName", "Unpaired Test Device"); + fakeNetworkPackage.set("protocolVersion", NetworkPackage.ProtocolVersion); + fakeNetworkPackage.set("deviceType", Device.DeviceType.Phone.toString()); + fakeNetworkPackage.set("certificate", Base64.encodeToString(certificate.getEncoded(), 0)); + + LanLinkProvider linkProvider = Mockito.mock(LanLinkProvider.class); + Mockito.when(linkProvider.getName()).thenReturn("LanLinkProvider"); + LanLink link = Mockito.mock(LanLink.class); + Mockito.when(link.getLinkProvider()).thenReturn(linkProvider); + Device device = new Device(getContext(), fakeNetworkPackage, link); + device.publicKey = keyPair.getPublic(); + + assertNotNull(device); + assertEquals(device.getDeviceId(), "unpairedTestDevice"); + assertEquals(device.getName(), "Unpaired Test Device"); + assertEquals(device.getDeviceType(), Device.DeviceType.Phone); + assertNotNull(device.publicKey); + assertNotNull(device.certificate); + + Method method; + try { + method = Device.class.getDeclaredMethod("pairingDone"); + method.setAccessible(true); + method.invoke(device); + }catch (Exception e){ + e.printStackTrace(); + } + + assertEquals(device.isPaired(), true); + + SharedPreferences preferences = getContext().getSharedPreferences("trusted_devices", Context.MODE_PRIVATE); + assertEquals(preferences.getBoolean(device.getDeviceId(), false), true); + + SharedPreferences settings = getContext().getSharedPreferences(device.getDeviceId(),Context.MODE_PRIVATE); + assertEquals(settings.getString("deviceName", "Unknown device"), "Unpaired Test Device"); + assertEquals(settings.getString("deviceType", "tablet"), "phone"); + assertEquals(settings.getString("publicKey", ""), Base64.encodeToString(keyPair.getPublic().getEncoded(), 0)); + assertEquals(settings.getString("certificate", ""), Base64.encodeToString(certificate.getEncoded(), 0));; + + // Cleanup for unpaired test device + preferences.edit().remove(device.getDeviceId()).apply(); + settings.edit().clear().apply(); + } + public void testUnpair(){ Device device = new Device(getContext(), "testDevice"); diff --git a/tests/org/kde/kdeconnect/LanLinkProviderTest.java b/tests/org/kde/kdeconnect/LanLinkProviderTest.java deleted file mode 100644 index fe7863a4..00000000 --- a/tests/org/kde/kdeconnect/LanLinkProviderTest.java +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Copyright 2015 Vineet Garg - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License or (at your option) version 3 or any later version - * accepted by the membership of KDE e.V. (or its successor approved - * by the membership of KDE e.V.), which shall act as a proxy - * defined in Section 14 of version 3 of the license. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . -*/ - -package org.kde.kdeconnect; - -import android.support.v4.util.LongSparseArray; -import android.test.AndroidTestCase; -import android.util.Log; - -import org.apache.mina.core.service.IoHandler; -import org.apache.mina.core.service.IoHandlerAdapter; -import org.apache.mina.core.session.IoSession; -import org.apache.mina.transport.socket.nio.NioDatagramAcceptor; -import org.apache.mina.transport.socket.nio.NioSocketAcceptor; -import org.kde.kdeconnect.Backends.LanBackend.LanLink; -import org.kde.kdeconnect.Backends.LanBackend.LanLinkProvider; -import org.mockito.Mockito; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; - -import java.io.InputStream; -import java.lang.reflect.Field; -import java.net.InetSocketAddress; -import java.net.ServerSocket; -import java.net.Socket; -import java.util.HashMap; - -public class LanLinkProviderTest extends AndroidTestCase { - - private NioSocketAcceptor tcpAcceptor = null; - private NioDatagramAcceptor udpAcceptor = null; - private LanLinkProvider linkProvider; - - @Override - protected void setUp() throws Exception { - super.setUp(); - - System.setProperty("dexmaker.dexcache", getContext().getCacheDir().getPath()); - - linkProvider = new LanLinkProvider(getContext()); - - try { - Field field = LanLinkProvider.class.getDeclaredField("tcpAcceptor"); - field.setAccessible(true); - tcpAcceptor = (NioSocketAcceptor)field.get(linkProvider); - assertNotNull(tcpAcceptor); - }catch (Exception e){ - fail("Error getting tcpAcceptor from LanLinkProvider"); - } - - try{ - Field field = LanLinkProvider.class.getDeclaredField("udpAcceptor"); - field.setAccessible(true); - udpAcceptor = (NioDatagramAcceptor)field.get(linkProvider); - assertNotNull(udpAcceptor); - }catch (Exception e){ - fail("Error getting udp acceptor from LanLinkProvider"); - } - - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - - tcpAcceptor.dispose(); - udpAcceptor.dispose(); - } - - public void testTcpAcceptor(){ - - assertNotNull(tcpAcceptor.getHandler()); - assertEquals(tcpAcceptor.getSessionConfig().isKeepAlive(), true); - assertEquals(tcpAcceptor.getSessionConfig().isReuseAddress(), true); - assertNotNull(tcpAcceptor.getFilterChain().get("codec")); - - } - - public void testUdpAcceptor(){ - - assertNull(udpAcceptor.getHandler()); - assertEquals(udpAcceptor.getSessionConfig().isReuseAddress(), true); - assertNotNull(udpAcceptor.getFilterChain().get("codec")); - } - - public void testOnStart() throws Exception{ - - IoSession session = Mockito.mock(IoSession.class); - Mockito.when(session.getId()).thenReturn(12345l); - Mockito.when(session.getRemoteAddress()).thenReturn(new InetSocketAddress(5000)); - - linkProvider.onStart(); - - assertNotNull(udpAcceptor.getHandler()); - assertEquals(udpAcceptor.getLocalAddress().getPort(), 1714); - } - - public void testUdpPackageReceived() throws Exception { - - final int port = 5000; - - NetworkPackage networkPackage = Mockito.mock(NetworkPackage.class); - Mockito.when(networkPackage.getType()).thenReturn("kdeconnect.identity"); - Mockito.when(networkPackage.getString("deviceId")).thenReturn("testDevice"); - Mockito.when(networkPackage.getString("deviceName")).thenReturn("Test Device"); - Mockito.when(networkPackage.getInt("protocolVersion")).thenReturn(NetworkPackage.ProtocolVersion); - Mockito.when(networkPackage.getString("deviceType")).thenReturn("phone"); - Mockito.when(networkPackage.getInt("tcpPort")).thenReturn(port); - - final String serialized = "{\"type\":\"kdeconnect.identity\",\"id\":12345,\"body\":{\"deviceName\":\"Test Device\",\"deviceType\":\"phone\",\"deviceId\":\"testDevice\",\"protocolVersion\":5,\"tcpPort\": "+ port +"}}"; - Mockito.when(networkPackage.serialize()).thenReturn(serialized); - - // Mocking udp session - IoSession session = Mockito.mock(IoSession.class); - Mockito.when(session.getId()).thenReturn(12345l); - Mockito.when(session.getRemoteAddress()).thenReturn(new InetSocketAddress(port)); - - - // Making a server socket, so that original LanLinkProvider can connect to it when it receives our fake package - final ServerSocket serverSocket = new ServerSocket(); - serverSocket.bind(new InetSocketAddress(port)); - - final Thread thread = new Thread (new Runnable() { - @Override - public void run() { - try { - Socket socket = serverSocket.accept(); - InputStream inputStream = socket.getInputStream(); - while (true) { - if (inputStream.available() != 0) { - // Data received from socket should be an identity package - byte[] inputData = new byte[inputStream.available()]; - inputStream.read(inputData); - - NetworkPackage receivedPackage = NetworkPackage.unserialize(new String(inputData)); - NetworkPackage identityPackage = NetworkPackage.createIdentityPackage(getContext()); - - // If any assertion fails, its output will be in logcat, not on test case thread anymore - assertEquals(receivedPackage.getType(), identityPackage.getType()); - assertEquals(receivedPackage.getString("deviceName"), identityPackage.getString("deviceName")); - assertEquals(receivedPackage.getString("deviceId"), identityPackage.getString("deviceId")); - assertEquals(receivedPackage.getInt("protocolVersion"), identityPackage.getInt("protocolVersion")); - - serverSocket.close(); - // Socket not closed to ensure visibleComputers contains entry for testDevice - break; - } - } - - }catch (Exception e){ - assertEquals("Exception in thread",1,5); - } - } - }); - - try { - thread.start(); - linkProvider.onStart(); - udpAcceptor.getHandler().messageReceived(session, networkPackage.serialize()); - }catch (Exception e){ - throw e; - } - - // Wait 1 secs for our server, and then end test - thread.join(1 * 1000); - - // visibleComputers should contain an entry for testDevice - HashMap visibleComputers; - try { - Field field = LanLinkProvider.class.getDeclaredField("visibleComputers"); - field.setAccessible(true); - visibleComputers = (HashMap)field.get(linkProvider); - }catch (Exception e){ - throw e; - } - assertNotNull(visibleComputers.get("testDevice")); - - } - - - public void testTcpIdentityPackageReceived() throws Exception{ - - IoSession session = Mockito.mock(IoSession.class); - Mockito.when(session.getId()).thenReturn(12345l); - - NetworkPackage networkPackage = Mockito.mock(NetworkPackage.class); - Mockito.when(networkPackage.getType()).thenReturn("kdeconnect.identity"); - Mockito.when(networkPackage.getString("deviceId")).thenReturn("testDevice"); - Mockito.when(networkPackage.getString("deviceName")).thenReturn("Test Device"); - Mockito.when(networkPackage.getInt("protocolVersion")).thenReturn(NetworkPackage.ProtocolVersion); - Mockito.when(networkPackage.getString("deviceType")).thenReturn("phone"); - - String serialized = "{\"type\":\"kdeconnect.identity\",\"id\":12345,\"body\":{\"deviceName\":\"Test Device\",\"deviceType\":\"phone\",\"deviceId\":\"testDevice\",\"protocolVersion\":5}}"; - Mockito.when(networkPackage.serialize()).thenReturn(serialized); - - try { - tcpAcceptor.getHandler().messageReceived(session, networkPackage.serialize()); - }catch (Exception e){ - throw e; - } - - LongSparseArray nioSessions; - try { - Field field = LanLinkProvider.class.getDeclaredField("nioSessions"); - field.setAccessible(true); - nioSessions = (LongSparseArray)field.get(linkProvider); - }catch (Exception e){ - throw e; - } - assertNotNull(nioSessions.get(12345l)); - - - HashMap visibleComputers; - try { - Field field = LanLinkProvider.class.getDeclaredField("visibleComputers"); - field.setAccessible(true); - visibleComputers = (HashMap)field.get(linkProvider); - }catch (Exception e){ - throw e; - } - assertNotNull(visibleComputers.get("testDevice")); - - - // Testing session closed - try { - tcpAcceptor.getHandler().sessionClosed(session); - }catch (Exception e){ - throw e; - } - assertNull(nioSessions.get(12345l)); - assertNull(visibleComputers.get("testDevice")); - } -} diff --git a/tests/org/kde/kdeconnect/LanLinkTest.java b/tests/org/kde/kdeconnect/LanLinkTest.java index d3d94c9c..86e2870f 100644 --- a/tests/org/kde/kdeconnect/LanLinkTest.java +++ b/tests/org/kde/kdeconnect/LanLinkTest.java @@ -23,8 +23,6 @@ package org.kde.kdeconnect; import android.test.AndroidTestCase; import android.util.Log; -import org.apache.mina.core.future.WriteFuture; -import org.apache.mina.core.session.IoSession; import org.json.JSONObject; import org.kde.kdeconnect.Backends.LanBackend.LanLink; import org.kde.kdeconnect.Backends.LanBackend.LanLinkProvider; @@ -34,17 +32,21 @@ import org.mockito.stubbing.Answer; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.io.InputStream; import java.net.InetSocketAddress; import java.net.Socket; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; + public class LanLinkTest extends AndroidTestCase { LanLink lanLink; - IoSession session; + Channel channel; Device.SendPackageStatusCallback callback; - WriteFuture writeFutureSuccess, writeFutureFailure; + ChannelFuture channelFutureSuccess, channelFutureFailure; @Override protected void setUp() throws Exception { @@ -55,9 +57,10 @@ public class LanLinkTest extends AndroidTestCase { LanLinkProvider linkProvider = Mockito.mock(LanLinkProvider.class); Mockito.when(linkProvider.getName()).thenReturn("LanLinkProvider"); - session = Mockito.mock(IoSession.class); - Mockito.when(session.getId()).thenReturn(12345l); - Mockito.when(session.getRemoteAddress()).thenReturn(new InetSocketAddress(5000)); + channel = Mockito.mock(Channel.class); +// Mockito.when(channel.hashCode()).thenReturn(12345); + Mockito.when(channel.remoteAddress()).thenReturn(new InetSocketAddress(5000)); +// Mockito.doReturn(new InetSocketAddress(5000)).when(channel).remoteAddress(); callback = Mockito.mock(Device.SendPackageStatusCallback.class); Mockito.doNothing().when(callback).sendSuccess(); @@ -69,18 +72,20 @@ public class LanLinkTest extends AndroidTestCase { } }).when(callback).sendFailure(Mockito.any(Throwable.class)); - writeFutureSuccess = Mockito.mock(WriteFuture.class); - Mockito.when(writeFutureSuccess.isWritten()).thenReturn(true); - Mockito.when(writeFutureSuccess.getSession()).thenReturn(session); - Mockito.when(writeFutureSuccess.isDone()).thenReturn(true); + channelFutureSuccess = Mockito.mock(ChannelFuture.class); + Mockito.when(channelFutureSuccess.isDone()).thenReturn(true); + Mockito.when(channelFutureSuccess.isSuccess()).thenReturn(true); + Mockito.when(channelFutureSuccess.channel()).thenReturn(channel); + Mockito.when(channelFutureSuccess.sync()).thenReturn(channelFutureSuccess); - writeFutureFailure = Mockito.mock(WriteFuture.class); - Mockito.when(writeFutureFailure.isWritten()).thenReturn(false); - Mockito.when(writeFutureFailure.getSession()).thenReturn(session); - Mockito.when(writeFutureFailure.isDone()).thenReturn(true); - Mockito.when(writeFutureFailure.getException()).thenReturn(new RuntimeException()); + channelFutureFailure = Mockito.mock(ChannelFuture.class); + Mockito.when(channelFutureFailure.isDone()).thenReturn(true); + Mockito.when(channelFutureFailure.isSuccess()).thenReturn(false); + Mockito.when(channelFutureFailure.cause()).thenReturn(new IOException("Cannot send package")); + Mockito.when(channelFutureFailure.channel()).thenReturn(channel); + Mockito.when(channelFutureFailure.sync()).thenReturn(channelFutureFailure); - lanLink = new LanLink(session, "testDevice", linkProvider); + lanLink = new LanLink(getContext(), channel, "testDevice", linkProvider); } @Override @@ -96,8 +101,15 @@ public class LanLinkTest extends AndroidTestCase { Mockito.when(testPackage.getString("testName")).thenReturn("testSendPackageSuccess"); Mockito.when(testPackage.serialize()).thenReturn("{\"id\":123,\"type\":\"kdeconnect.test\",\"body\":{\"isTesting\":true,\"testName\":\"testSendPackageSuccess\"}}"); - Mockito.when(session.write(testPackage.serialize())).thenReturn(writeFutureSuccess); - lanLink.sendPackage(testPackage, callback); + try { + Mockito.when(channel.writeAndFlush(testPackage.serialize())).thenReturn(channelFutureSuccess); + lanLink.sendPackage(testPackage, callback); + } catch (Exception e) { + e.printStackTrace(); + } + + assertEquals(channelFutureSuccess.isDone(), true); + assertEquals(channelFutureSuccess.isSuccess(), true); } public void testSendPackageFail(){ @@ -108,17 +120,16 @@ public class LanLinkTest extends AndroidTestCase { Mockito.when(testPackage.getString("testName")).thenReturn("testSendPackageFail"); Mockito.when(testPackage.serialize()).thenReturn("{\"id\":123,\"type\":\"kdeconnect.test\",\"body\":{\"isTesting\":true,\"testName\":\"testSendPackageFail\"}}"); - Mockito.when(session.write(testPackage.serialize())).thenReturn(writeFutureFailure); try { + Mockito.when(channel.writeAndFlush(testPackage.serialize())).thenReturn(channelFutureFailure); lanLink.sendPackage(testPackage, callback); - }catch (RuntimeException r){ - // Do nothing, test is fine, callback should throw this exception - }catch (Exception e){ - // This should not happen - throw e; + } catch (Exception e) { + e.printStackTrace(); } - + assertEquals(channelFutureFailure.isDone(), true); + assertEquals(channelFutureFailure.isSuccess(), false); + assertEquals(channelFutureFailure.cause() instanceof IOException, true ); } @@ -145,7 +156,7 @@ public class LanLinkTest extends AndroidTestCase { try { socket = new Socket(); int tcpPort = np.getPayloadTransferInfo().getInt("port"); - InetSocketAddress address = (InetSocketAddress)session.getRemoteAddress(); + InetSocketAddress address = (InetSocketAddress)channel.remoteAddress(); socket.connect(new InetSocketAddress(address.getAddress(), tcpPort)); np.setPayload(socket.getInputStream(), np.getPayloadSize()); } catch (Exception e) { @@ -246,9 +257,9 @@ public class LanLinkTest extends AndroidTestCase { downloader.setNetworkPackage(np); downloader.start(); - return writeFutureSuccess; + return channelFutureSuccess; } - }).when(session).write(Mockito.anyString()); + }).when(channel).writeAndFlush(Mockito.anyString()); lanLink.sendPackage(sharePackage, callback); diff --git a/tests/org/kde/kdeconnect/NetworkPackageTest.java b/tests/org/kde/kdeconnect/NetworkPackageTest.java index a21114ec..09dd376c 100644 --- a/tests/org/kde/kdeconnect/NetworkPackageTest.java +++ b/tests/org/kde/kdeconnect/NetworkPackageTest.java @@ -23,6 +23,8 @@ package org.kde.kdeconnect; import android.test.AndroidTestCase; import android.util.Log; +import org.kde.kdeconnect.Helpers.SecurityHelpers.RsaHelper; + import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; @@ -106,10 +108,10 @@ public class NetworkPackageTest extends AndroidTestCase{ // Encrypt and decrypt np assertEquals(original.getType(), "com.test"); try { - NetworkPackage encrypted = original.encrypt(publicKey); + NetworkPackage encrypted = RsaHelper.encrypt(original,publicKey); assertEquals(encrypted.getType(), NetworkPackage.PACKAGE_TYPE_ENCRYPTED); - decrypted = encrypted.decrypt(privateKey); + decrypted = RsaHelper.decrypt(encrypted, privateKey); assertEquals(decrypted.getType(), "com.test"); }catch (Exception e){ @@ -124,8 +126,8 @@ public class NetworkPackageTest extends AndroidTestCase{ String json = "{\"body\":{\"nowPlaying\":\"A really long song name - A really long artist name\",\"player\":\"A really long player name\",\"the_meaning_of_life_the_universe_and_everything\":\"42\"},\"id\":\"A really long package id\",\"payloadSize\":0,\"payloadTransferInfo\":{},\"type\":\"kdeconnect.a_really_really_long_package_type\"}\n"; NetworkPackage longJsonNp = NetworkPackage.unserialize(json); try { - NetworkPackage encrypted = longJsonNp.encrypt(publicKey); - decrypted = encrypted.decrypt(privateKey); + NetworkPackage encrypted = RsaHelper.encrypt(longJsonNp, publicKey); + decrypted = RsaHelper.decrypt(encrypted, privateKey); String decryptedJson = decrypted.serialize(); assertEquals(json, decryptedJson);