OXInstantMessagingIntegrationTest.java

  1. /**
  2.  *
  3.  * Copyright 2018 Paul Schaub.
  4.  *
  5.  * Licensed under the Apache License, Version 2.0 (the "License");
  6.  * you may not use this file except in compliance with the License.
  7.  * You may obtain a copy of the License at
  8.  *
  9.  *     http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.jivesoftware.smackx.ox_im;

  18. import static org.junit.jupiter.api.Assertions.assertFalse;
  19. import static org.junit.jupiter.api.Assertions.assertTrue;

  20. import java.io.File;
  21. import java.io.IOException;

  22. import org.jivesoftware.smack.SmackException;
  23. import org.jivesoftware.smack.XMPPException;
  24. import org.jivesoftware.smack.packet.Message;
  25. import org.jivesoftware.smack.util.StringUtils;

  26. import org.jivesoftware.smackx.ox.AbstractOpenPgpIntegrationTest;
  27. import org.jivesoftware.smackx.ox.OpenPgpContact;
  28. import org.jivesoftware.smackx.ox.OpenPgpManager;
  29. import org.jivesoftware.smackx.ox.crypto.PainlessOpenPgpProvider;
  30. import org.jivesoftware.smackx.ox.element.SigncryptElement;
  31. import org.jivesoftware.smackx.ox.store.filebased.FileBasedOpenPgpStore;
  32. import org.jivesoftware.smackx.ox.util.OpenPgpPubSubUtil;

  33. import org.igniterealtime.smack.inttest.SmackIntegrationTestEnvironment;
  34. import org.igniterealtime.smack.inttest.TestNotPossibleException;
  35. import org.igniterealtime.smack.inttest.annotations.AfterClass;
  36. import org.igniterealtime.smack.inttest.annotations.BeforeClass;
  37. import org.igniterealtime.smack.inttest.annotations.SmackIntegrationTest;
  38. import org.igniterealtime.smack.inttest.annotations.SpecificationReference;
  39. import org.igniterealtime.smack.inttest.util.SimpleResultSyncPoint;
  40. import org.pgpainless.decryption_verification.OpenPgpMetadata;
  41. import org.pgpainless.key.OpenPgpV4Fingerprint;
  42. import org.pgpainless.key.protection.UnprotectedKeysProtector;

  43. @SpecificationReference(document = "XEP-0374", version = "0.2.0")
  44. public class OXInstantMessagingIntegrationTest extends AbstractOpenPgpIntegrationTest {

  45.     private static final String sessionId = StringUtils.randomString(10);
  46.     private static final File tempDir = org.apache.commons.io.FileUtils.getTempDirectory();
  47.     private static final File aliceStorePath = new File(tempDir, "basic_ox_messaging_test_alice_" + sessionId);
  48.     private static final File bobStorePath = new File(tempDir, "basic_ox_messaging_test_bob_" + sessionId);

  49.     private OpenPgpV4Fingerprint aliceFingerprint = null;
  50.     private OpenPgpV4Fingerprint bobFingerprint = null;

  51.     private OpenPgpManager aliceOpenPgp;
  52.     private OpenPgpManager bobOpenPgp;

  53.     /**
  54.      * This integration test tests basic OX message exchange.
  55.      * In this scenario, Alice and Bob are strangers, as they do not have subscribed to one another.
  56.      *
  57.      * Alice (conOne) creates keys and publishes them to the server.
  58.      * Bob (conTwo) creates keys and publishes them to the server.
  59.      *
  60.      * Alice then manually fetches Bobs metadata node and all announced keys.
  61.      *
  62.      * Alice trusts Bobs keys and vice versa (even though Bob does not have copies of Alice' keys yet).
  63.      *
  64.      * She proceeds to create an OX encrypted message, which is encrypted to Bob and herself and signed by her.
  65.      *
  66.      * She sends the message.
  67.      *
  68.      * Bob receives the message, which - due to missing keys - triggers him to update Alice' keys.
  69.      *
  70.      * After the update Bob proceeds to decrypt and verify the message.
  71.      *
  72.      * After the test, the keys are deleted from local storage and from PubSub.
  73.      *
  74.      * @param environment test environment
  75.      *
  76.      * @throws XMPPException.XMPPErrorException if there was an XMPP error returned.
  77.      * @throws InterruptedException if the calling thread was interrupted.
  78.      * @throws SmackException.NotConnectedException if the XMPP connection is not connected.
  79.      * @throws TestNotPossibleException if the test is not possible due to lacking server support for PEP.
  80.      * @throws SmackException.NoResponseException if there was no response from the remote entity.
  81.      */
  82.     public OXInstantMessagingIntegrationTest(SmackIntegrationTestEnvironment environment)
  83.             throws XMPPException.XMPPErrorException, InterruptedException, SmackException.NotConnectedException,
  84.             TestNotPossibleException, SmackException.NoResponseException {
  85.         super(environment);
  86.     }

  87.     @BeforeClass
  88.     @AfterClass
  89.     public static void deleteStore() throws IOException {
  90.         org.apache.commons.io.FileUtils.deleteDirectory(aliceStorePath);
  91.         org.apache.commons.io.FileUtils.deleteDirectory(bobStorePath);
  92.     }

  93.     @SmackIntegrationTest
  94.     public void basicInstantMessagingTest()
  95.             throws Exception {

  96.         final SimpleResultSyncPoint bobReceivedMessage = new SimpleResultSyncPoint();
  97.         final String body = "Writing integration tests is an annoying task, but it has to be done, so lets do it!!!";

  98.         FileBasedOpenPgpStore aliceStore = new FileBasedOpenPgpStore(aliceStorePath);
  99.         aliceStore.setKeyRingProtector(new UnprotectedKeysProtector());
  100.         FileBasedOpenPgpStore bobStore = new FileBasedOpenPgpStore(bobStorePath);
  101.         bobStore.setKeyRingProtector(new UnprotectedKeysProtector());

  102.         PainlessOpenPgpProvider aliceProvider = new PainlessOpenPgpProvider(aliceStore);
  103.         PainlessOpenPgpProvider bobProvider = new PainlessOpenPgpProvider(bobStore);

  104.         aliceOpenPgp = OpenPgpManager.getInstanceFor(aliceConnection);
  105.         bobOpenPgp = OpenPgpManager.getInstanceFor(bobConnection);

  106.         OXInstantMessagingManager aliceInstantMessaging = OXInstantMessagingManager.getInstanceFor(aliceConnection);
  107.         OXInstantMessagingManager bobInstantMessaging = OXInstantMessagingManager.getInstanceFor(bobConnection);

  108.         bobInstantMessaging.addOxMessageListener(new OxMessageListener() {
  109.             @Override
  110.             public void newIncomingOxMessage(OpenPgpContact contact, Message originalMessage, SigncryptElement decryptedPayload, OpenPgpMetadata metadata) {
  111.                 if (((Message.Body) decryptedPayload.getExtension(Message.Body.NAMESPACE)).getMessage().equals(body)) {
  112.                     bobReceivedMessage.signal();
  113.                 } else {
  114.                     bobReceivedMessage.signalFailure();
  115.                 }
  116.             }
  117.         });

  118.         aliceOpenPgp.setOpenPgpProvider(aliceProvider);
  119.         bobOpenPgp.setOpenPgpProvider(bobProvider);

  120.         aliceFingerprint = aliceOpenPgp.generateAndImportKeyPair(alice);
  121.         bobFingerprint = bobOpenPgp.generateAndImportKeyPair(bob);

  122.         try {
  123.             aliceOpenPgp.announceSupportAndPublish();
  124.             bobOpenPgp.announceSupportAndPublish();

  125.             OpenPgpContact bobForAlice = aliceOpenPgp.getOpenPgpContact(bob.asEntityBareJidIfPossible());
  126.             OpenPgpContact aliceForBob = bobOpenPgp.getOpenPgpContact(alice.asEntityBareJidIfPossible());

  127.             bobForAlice.updateKeys(aliceConnection);

  128.             assertFalse(bobForAlice.isTrusted(bobFingerprint));
  129.             assertFalse(aliceForBob.isTrusted(aliceFingerprint));

  130.             bobForAlice.trust(bobFingerprint);
  131.             aliceForBob.trust(aliceFingerprint);

  132.             assertTrue(bobForAlice.isTrusted(bobFingerprint));
  133.             assertTrue(aliceForBob.isTrusted(aliceFingerprint));

  134.             aliceInstantMessaging.sendOxMessage(bobForAlice, body);

  135.             bobReceivedMessage.waitForResult(timeout);
  136.         } finally {
  137.             OpenPgpPubSubUtil.deletePublicKeyNode(alicePepManager, aliceFingerprint);
  138.             OpenPgpPubSubUtil.deletePubkeysListNode(alicePepManager);
  139.             OpenPgpPubSubUtil.deletePublicKeyNode(bobPepManager, bobFingerprint);
  140.             OpenPgpPubSubUtil.deletePubkeysListNode(bobPepManager);
  141.         }
  142.     }

  143. }