From 8497c03035e11316537e2082aefc9d036cb89feb Mon Sep 17 00:00:00 2001 From: wenjunche Date: Wed, 18 Aug 2021 16:44:02 -0400 Subject: [PATCH 1/4] DTNT-528: added tests for snapshot API --- .../java/com/openfin/desktop/AllTests.java | 2 +- .../com/openfin/desktop/SnapshotTest.java | 128 ++++++++++++++++++ 2 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 src/test/java/com/openfin/desktop/SnapshotTest.java diff --git a/src/test/java/com/openfin/desktop/AllTests.java b/src/test/java/com/openfin/desktop/AllTests.java index 68f0374..b34e8ee 100644 --- a/src/test/java/com/openfin/desktop/AllTests.java +++ b/src/test/java/com/openfin/desktop/AllTests.java @@ -10,6 +10,6 @@ */ @RunWith(Suite.class) -@Suite.SuiteClasses({ ApplicationTest.class, OpenFinRuntimeTest.class, WindowTest.class, SystemTest.class, InterApplicationBusTest.class, ChannelTest.class, RuntimeConfigTest.class}) +@Suite.SuiteClasses({ ApplicationTest.class, OpenFinRuntimeTest.class, WindowTest.class, SystemTest.class, InterApplicationBusTest.class, ChannelTest.class, RuntimeConfigTest.class, SnapshotTest.class}) public class AllTests { } diff --git a/src/test/java/com/openfin/desktop/SnapshotTest.java b/src/test/java/com/openfin/desktop/SnapshotTest.java new file mode 100644 index 0000000..f8e3cae --- /dev/null +++ b/src/test/java/com/openfin/desktop/SnapshotTest.java @@ -0,0 +1,128 @@ +package com.openfin.desktop; + +import com.openfin.desktop.snapshot.SnapshotSource; +import com.openfin.desktop.snapshot.SnapshotSourceProvider; +import com.sun.xml.internal.bind.v2.runtime.unmarshaller.LocatorEx; +import org.json.JSONArray; +import org.json.JSONObject; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +public class SnapshotTest implements SnapshotSourceProvider { + + private static Logger logger = LoggerFactory.getLogger(SnapshotTest.class.getName()); + + private static final String DESKTOP_UUID = SnapshotTest.class.getName(); + private static DesktopConnection desktopConnection; + private static OpenFinRuntime runtime; + private static SnapshotSource snapshotSource; + private static final JSONObject SNAPSHOT_CONTENT = new JSONObject("{width: 123}"); + + private JSONObject randomSnapshot; + + @BeforeClass + public static void setup() throws Exception { + logger.debug("starting"); + desktopConnection = TestUtils.setupConnection(DESKTOP_UUID); + if (desktopConnection != null) { + runtime = new OpenFinRuntime(desktopConnection); + snapshotSource = new SnapshotSource(desktopConnection); + } + } + + @AfterClass + public static void teardown() throws Exception { + TestUtils.teardownDesktopConnection(desktopConnection); + } + + @Test + public void initProviderThenCreateClient() throws Exception { + CountDownLatch latch = new CountDownLatch(2); + final String appUuid = "initProviderThenCreateClient"; + snapshotSource.initSnapshotSourceProviderAsync(appUuid, this).thenAccept(provider -> { + logger.debug("Snapshot provider created"); + latch.countDown(); + }); + snapshotSource.createSnapshotSourceClientAsync(appUuid).thenAccept(client -> { + logger.debug("Snapshot client created"); + latch.countDown(); + }); + + latch.await(5, TimeUnit.SECONDS); + + assertEquals("initProviderThenCreateClient timeout", latch.getCount(), 0); + } + + @Test + public void initProviderThenCreateClientThenGetSnapshot() throws Exception { + CountDownLatch latch = new CountDownLatch(2); + final String appUuid = "initProviderThenCreateClientThenGetSnapshot"; + snapshotSource.initSnapshotSourceProviderAsync(appUuid, this).thenAccept(provider -> { + logger.debug("Snapshot provider created"); + latch.countDown(); + }); + + snapshotSource.createSnapshotSourceClientAsync(appUuid).thenAccept(client -> { + client.getSnapshotAsync().thenAccept(ack -> { + JSONObject snapshot = ((JSONObject) ack.getData()).getJSONObject("result"); + if (SNAPSHOT_CONTENT.toString().equals(snapshot.toString())) { + latch.countDown(); + } + }); + }); + + latch.await(5, TimeUnit.SECONDS); + + assertEquals("initProviderThenCreateClientThenGetSnapshot timeout", latch.getCount(), 0); + } + + @Test + public void initProviderThenCreateClientThenApplySnapshot() throws Exception { + CountDownLatch latch = new CountDownLatch(2); + final JSONObject random = new JSONObject(String.format("{value: %f}", Math.random())); + final String appUuid = "initProviderThenCreateClientThenApplySnapshot"; + snapshotSource.initSnapshotSourceProviderAsync(appUuid, this).thenAccept(provider -> { + latch.countDown(); + }); + + snapshotSource.createSnapshotSourceClientAsync(appUuid).thenAccept(client -> { + client.applySnapshotAsync(random).thenAccept(ack -> { + client.getSnapshotAsync().thenAccept(ack1 -> { + JSONObject snapshot = ((JSONObject) ack1.getData()).getJSONObject("result"); + if (random.toString().equals(snapshot.toString())) { + latch.countDown(); + } + }); + + }); + }); + + latch.await(5, TimeUnit.SECONDS); + + assertEquals("initProviderThenCreateClientThenGetSnapshot timeout", latch.getCount(), 0); + } + + @Override + public JSONObject getSnapshot() { + if (this.randomSnapshot != null) { + return this.randomSnapshot; + } else { + return SNAPSHOT_CONTENT; + } + } + + @Override + public void applySnapshot(JSONObject snapshot) { + this.randomSnapshot = snapshot; + } +} From d2232368fbc689e39f27c9922302b65e622c3542 Mon Sep 17 00:00:00 2001 From: wenjunche Date: Wed, 18 Aug 2021 16:58:02 -0400 Subject: [PATCH 2/4] DTNT-528: review from Anthony --- src/test/java/com/openfin/desktop/SnapshotTest.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/openfin/desktop/SnapshotTest.java b/src/test/java/com/openfin/desktop/SnapshotTest.java index f8e3cae..bff74a3 100644 --- a/src/test/java/com/openfin/desktop/SnapshotTest.java +++ b/src/test/java/com/openfin/desktop/SnapshotTest.java @@ -73,8 +73,7 @@ public void initProviderThenCreateClientThenGetSnapshot() throws Exception { }); snapshotSource.createSnapshotSourceClientAsync(appUuid).thenAccept(client -> { - client.getSnapshotAsync().thenAccept(ack -> { - JSONObject snapshot = ((JSONObject) ack.getData()).getJSONObject("result"); + client.getSnapshotAsync().thenAccept(snapshot -> { if (SNAPSHOT_CONTENT.toString().equals(snapshot.toString())) { latch.countDown(); } @@ -97,8 +96,7 @@ public void initProviderThenCreateClientThenApplySnapshot() throws Exception { snapshotSource.createSnapshotSourceClientAsync(appUuid).thenAccept(client -> { client.applySnapshotAsync(random).thenAccept(ack -> { - client.getSnapshotAsync().thenAccept(ack1 -> { - JSONObject snapshot = ((JSONObject) ack1.getData()).getJSONObject("result"); + client.getSnapshotAsync().thenAccept(snapshot -> { if (random.toString().equals(snapshot.toString())) { latch.countDown(); } From a9d261494d0a79e57bfa89767e1be0a1d7ec512f Mon Sep 17 00:00:00 2001 From: wenjunche Date: Sat, 21 Aug 2021 13:15:15 -0400 Subject: [PATCH 3/4] DTNT-528 updated signer.java --- .../java/com/openfin/desktop/demo/Signer.java | 98 ++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/openfin/desktop/demo/Signer.java b/src/main/java/com/openfin/desktop/demo/Signer.java index 22a611b..4c3bd42 100644 --- a/src/main/java/com/openfin/desktop/demo/Signer.java +++ b/src/main/java/com/openfin/desktop/demo/Signer.java @@ -1,2 +1,98 @@ -package com.openfin.desktop.demo;public class Signer { +package com.openfin.desktop.demo; + +import java.io.InputStream; +import java.security.CodeSigner; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.jar.Attributes; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.jar.Manifest; + +public class Signer { + private final String filename; + + public Signer(String filename) { + this.filename = filename; + } + + public void verify() throws Exception { + JarFile jar = new JarFile(this.filename, true); + + Enumeration entries = jar.entries(); + while (entries.hasMoreElements()) { + JarEntry entry = entries.nextElement(); + byte[] buffer = new byte[8192]; + InputStream is = jar.getInputStream(entry); + while ((is.read(buffer, 0, buffer.length)) != -1) { + // We just read. This will throw a SecurityException + // if a signature/digest check fails. + } + is.close(); + } + + if (!checkSign(jar)) { + throw new SecurityException("not signed"); + } + + } + + private boolean checkSign(JarFile jar) throws Exception { + InputStream jis = jar.getInputStream(jar.getEntry("META-INF/MANIFEST.MF")); + Manifest man = new Manifest(jis); + jis.close(); + + HashSet signed = new HashSet<>(); + for(Map.Entry entry: man.getEntries().entrySet()) { + for(Object attrkey: entry.getValue().keySet()) { + if (attrkey instanceof Attributes.Name && attrkey.toString().contains("-Digest")) { + signed.add(entry.getKey()); + } + } + } + System.out.printf("Number of Digest from manifest %d \n", signed.size()); + + Set entries = new HashSet<>(); + for(Enumeration entry = jar.entries(); entry.hasMoreElements(); ) { + JarEntry je = entry.nextElement(); + String fileName = je.getName().toUpperCase(); + if (!je.isDirectory() + && !fileName.endsWith(".MF") + && !fileName.endsWith(".SF") + && !fileName.endsWith(".DSA") + && !fileName.endsWith(".EC") + && !fileName.endsWith(".RSA") + ) { + CodeSigner[] signers = je.getCodeSigners(); + if (signers != null && signers.length == 1) { + CodeSigner signer = signers[0]; + if (signer.getSignerCertPath().getCertificates().size() != 4) { + throw new SecurityException(String.format("invalid cert chain %s", je.getName())); + } + X509Certificate cert = (X509Certificate) signer.getSignerCertPath().getCertificates().get(0); + if (!cert.getSubjectDN().toString().contains("OpenFin Inc.")) { + throw new SecurityException(String.format("invalid signed %s", je.getName())); + } + entries.add(je.getName()); + } else { + throw new SecurityException(String.format("missing cert %s", je.getName())); + } + } + } + System.out.printf("Number of signed entries %d \n", entries.size()); + + Set unsigned = new HashSet<>(entries); + unsigned.removeAll(signed); + return unsigned.size() == 0; + } + + public static void main(String[] args) throws Exception { + Signer signer = new Signer(args[0]); + signer.verify(); + } + } From 1cb92ac003d378ee7c3dd8c1852e51dd613c5667 Mon Sep 17 00:00:00 2001 From: wenjunche Date: Wed, 25 Aug 2021 19:23:58 -0400 Subject: [PATCH 4/4] DTNT-528: update tests for snapshot API --- .../java/com/openfin/desktop/SnapshotTest.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/test/java/com/openfin/desktop/SnapshotTest.java b/src/test/java/com/openfin/desktop/SnapshotTest.java index bff74a3..fc8c676 100644 --- a/src/test/java/com/openfin/desktop/SnapshotTest.java +++ b/src/test/java/com/openfin/desktop/SnapshotTest.java @@ -25,7 +25,6 @@ public class SnapshotTest implements SnapshotSourceProvider { private static final String DESKTOP_UUID = SnapshotTest.class.getName(); private static DesktopConnection desktopConnection; private static OpenFinRuntime runtime; - private static SnapshotSource snapshotSource; private static final JSONObject SNAPSHOT_CONTENT = new JSONObject("{width: 123}"); private JSONObject randomSnapshot; @@ -36,7 +35,6 @@ public static void setup() throws Exception { desktopConnection = TestUtils.setupConnection(DESKTOP_UUID); if (desktopConnection != null) { runtime = new OpenFinRuntime(desktopConnection); - snapshotSource = new SnapshotSource(desktopConnection); } } @@ -49,11 +47,11 @@ public static void teardown() throws Exception { public void initProviderThenCreateClient() throws Exception { CountDownLatch latch = new CountDownLatch(2); final String appUuid = "initProviderThenCreateClient"; - snapshotSource.initSnapshotSourceProviderAsync(appUuid, this).thenAccept(provider -> { + desktopConnection.getSnapshotSource().initSnapshotSourceProviderAsync(appUuid, this).thenAccept(provider -> { logger.debug("Snapshot provider created"); latch.countDown(); }); - snapshotSource.createSnapshotSourceClientAsync(appUuid).thenAccept(client -> { + desktopConnection.getSnapshotSource().createSnapshotSourceClientAsync(appUuid).thenAccept(client -> { logger.debug("Snapshot client created"); latch.countDown(); }); @@ -67,12 +65,12 @@ public void initProviderThenCreateClient() throws Exception { public void initProviderThenCreateClientThenGetSnapshot() throws Exception { CountDownLatch latch = new CountDownLatch(2); final String appUuid = "initProviderThenCreateClientThenGetSnapshot"; - snapshotSource.initSnapshotSourceProviderAsync(appUuid, this).thenAccept(provider -> { + desktopConnection.getSnapshotSource().initSnapshotSourceProviderAsync(appUuid, this).thenAccept(provider -> { logger.debug("Snapshot provider created"); latch.countDown(); }); - snapshotSource.createSnapshotSourceClientAsync(appUuid).thenAccept(client -> { + desktopConnection.getSnapshotSource().createSnapshotSourceClientAsync(appUuid).thenAccept(client -> { client.getSnapshotAsync().thenAccept(snapshot -> { if (SNAPSHOT_CONTENT.toString().equals(snapshot.toString())) { latch.countDown(); @@ -90,11 +88,11 @@ public void initProviderThenCreateClientThenApplySnapshot() throws Exception { CountDownLatch latch = new CountDownLatch(2); final JSONObject random = new JSONObject(String.format("{value: %f}", Math.random())); final String appUuid = "initProviderThenCreateClientThenApplySnapshot"; - snapshotSource.initSnapshotSourceProviderAsync(appUuid, this).thenAccept(provider -> { + desktopConnection.getSnapshotSource().initSnapshotSourceProviderAsync(appUuid, this).thenAccept(provider -> { latch.countDown(); }); - snapshotSource.createSnapshotSourceClientAsync(appUuid).thenAccept(client -> { + desktopConnection.getSnapshotSource().createSnapshotSourceClientAsync(appUuid).thenAccept(client -> { client.applySnapshotAsync(random).thenAccept(ack -> { client.getSnapshotAsync().thenAccept(snapshot -> { if (random.toString().equals(snapshot.toString())) {