smack-omemo*: Do not swallow IOException deep within the library

Those exception are caused by I/O operations in the OmemoStore, which
is now declaring that it throws those (since it is not uncommon for
I/O operations to cause IOExceptions). After all, this is nicely
demonstrated as this change is caused by switching with this commit to
the Android API 19 compatible methods in FileBasedOmemoStore, which
throw.

The library can not decide what to do in case of those exceptions,
hence it is sensible to expose them to the user.
This commit is contained in:
Florian Schmaus 2019-08-05 08:28:42 +02:00
parent 699905a1de
commit 1bce378e6d
16 changed files with 299 additions and 331 deletions

View File

@ -19,6 +19,7 @@ package org.jivesoftware.smackx.omemo;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import java.io.IOException;
import java.util.logging.Level; import java.util.logging.Level;
import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.SmackException;
@ -64,7 +65,7 @@ public abstract class AbstractTwoUsersOmemoIntegrationTest extends AbstractOmemo
} }
@AfterClass @AfterClass
public void cleanUp() { public void cleanUp() throws IOException {
alice.stopStanzaAndPEPListeners(); alice.stopStanzaAndPEPListeners();
bob.stopStanzaAndPEPListeners(); bob.stopStanzaAndPEPListeners();
OmemoManagerSetupHelper.cleanUpPubSub(alice); OmemoManagerSetupHelper.cleanUpPubSub(alice);

View File

@ -18,6 +18,7 @@ package org.jivesoftware.smackx.omemo;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import java.io.IOException;
import java.util.List; import java.util.List;
import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.SmackException;
@ -50,7 +51,7 @@ public class OmemoMamDecryptionTest extends AbstractTwoUsersOmemoIntegrationTest
@SmackIntegrationTest @SmackIntegrationTest
public void mamDecryptionTest() throws XMPPException.XMPPErrorException, SmackException.NotLoggedInException, public void mamDecryptionTest() throws XMPPException.XMPPErrorException, SmackException.NotLoggedInException,
SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException, SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException,
CryptoFailedException, UndecidedOmemoIdentityException { CryptoFailedException, UndecidedOmemoIdentityException, IOException {
// Make sure, Bobs server stores messages in the archive // Make sure, Bobs server stores messages in the archive
MamManager bobsMamManager = MamManager.getInstanceFor(bob.getConnection()); MamManager bobsMamManager = MamManager.getInstanceFor(bob.getConnection());
bobsMamManager.enableMamForAllMessages(); bobsMamManager.enableMamForAllMessages();

View File

@ -20,6 +20,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.SmackException;
@ -46,7 +47,7 @@ public class OmemoManagerSetupHelper {
public static void trustAllIdentities(OmemoManager alice, OmemoManager bob) public static void trustAllIdentities(OmemoManager alice, OmemoManager bob)
throws InterruptedException, SmackException.NotConnectedException, SmackException.NotLoggedInException, throws InterruptedException, SmackException.NotConnectedException, SmackException.NotLoggedInException,
SmackException.NoResponseException, CannotEstablishOmemoSessionException, CorruptedOmemoKeyException, SmackException.NoResponseException, CannotEstablishOmemoSessionException, CorruptedOmemoKeyException,
XMPPException.XMPPErrorException, PubSubException.NotALeafNodeException { XMPPException.XMPPErrorException, PubSubException.NotALeafNodeException, IOException {
Roster roster = Roster.getInstanceFor(alice.getConnection()); Roster roster = Roster.getInstanceFor(alice.getConnection());
if (alice.getOwnJid() != bob.getOwnJid() && if (alice.getOwnJid() != bob.getOwnJid() &&
@ -66,7 +67,7 @@ public class OmemoManagerSetupHelper {
public static void trustAllIdentitiesWithTests(OmemoManager alice, OmemoManager bob) public static void trustAllIdentitiesWithTests(OmemoManager alice, OmemoManager bob)
throws InterruptedException, SmackException.NotConnectedException, SmackException.NotLoggedInException, throws InterruptedException, SmackException.NotConnectedException, SmackException.NotLoggedInException,
SmackException.NoResponseException, CannotEstablishOmemoSessionException, CorruptedOmemoKeyException, SmackException.NoResponseException, CannotEstablishOmemoSessionException, CorruptedOmemoKeyException,
XMPPException.XMPPErrorException, PubSubException.NotALeafNodeException { XMPPException.XMPPErrorException, PubSubException.NotALeafNodeException, IOException {
alice.requestDeviceListUpdateFor(bob.getOwnJid()); alice.requestDeviceListUpdateFor(bob.getOwnJid());
HashMap<OmemoDevice, OmemoFingerprint> fps1 = alice.getActiveFingerprints(bob.getOwnJid()); HashMap<OmemoDevice, OmemoFingerprint> fps1 = alice.getActiveFingerprints(bob.getOwnJid());
@ -124,7 +125,7 @@ public class OmemoManagerSetupHelper {
} }
} }
public static void cleanUpPubSub(OmemoManager omemoManager) { public static void cleanUpPubSub(OmemoManager omemoManager) throws IOException {
PubSubManager pm = PubSubManager.getInstanceFor(omemoManager.getConnection(), omemoManager.getOwnJid()); PubSubManager pm = PubSubManager.getInstanceFor(omemoManager.getConnection(), omemoManager.getOwnJid());
try { try {
omemoManager.requestDeviceListUpdateFor(omemoManager.getOwnJid()); omemoManager.requestDeviceListUpdateFor(omemoManager.getOwnJid());

View File

@ -20,6 +20,8 @@ import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertFalse; import static junit.framework.TestCase.assertFalse;
import static junit.framework.TestCase.assertTrue; import static junit.framework.TestCase.assertTrue;
import java.io.IOException;
import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smackx.omemo.exceptions.CryptoFailedException; import org.jivesoftware.smackx.omemo.exceptions.CryptoFailedException;
@ -37,7 +39,9 @@ public class ReadOnlyDeviceIntegrationTest extends AbstractTwoUsersOmemoIntegrat
} }
@SmackIntegrationTest @SmackIntegrationTest
public void test() throws InterruptedException, SmackException.NoResponseException, SmackException.NotLoggedInException, SmackException.NotConnectedException, CryptoFailedException, UndecidedOmemoIdentityException { public void test() throws InterruptedException, SmackException.NoResponseException,
SmackException.NotLoggedInException, SmackException.NotConnectedException, CryptoFailedException,
UndecidedOmemoIdentityException, IOException {
boolean prevIgnoreReadOnlyConf = OmemoConfiguration.getIgnoreReadOnlyDevices(); boolean prevIgnoreReadOnlyConf = OmemoConfiguration.getIgnoreReadOnlyDevices();
int prevMaxMessageCounter = OmemoConfiguration.getMaxReadOnlyMessageCount(); int prevMaxMessageCounter = OmemoConfiguration.getMaxReadOnlyMessageCount();

View File

@ -20,6 +20,7 @@
*/ */
package org.jivesoftware.smackx.omemo.signal; package org.jivesoftware.smackx.omemo.signal;
import java.io.IOException;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -73,7 +74,7 @@ public class SignalOmemoRatchet
@Override @Override
public byte[] doubleRatchetDecrypt(OmemoDevice sender, byte[] encryptedKey) public byte[] doubleRatchetDecrypt(OmemoDevice sender, byte[] encryptedKey)
throws CorruptedOmemoKeyException, NoRawSessionException, CryptoFailedException, throws CorruptedOmemoKeyException, NoRawSessionException, CryptoFailedException,
UntrustedOmemoIdentityException { UntrustedOmemoIdentityException, IOException {
SessionCipher cipher = getCipher(sender); SessionCipher cipher = getCipher(sender);
byte[] decryptedKey; byte[] decryptedKey;

View File

@ -20,6 +20,7 @@
*/ */
package org.jivesoftware.smackx.omemo.signal; package org.jivesoftware.smackx.omemo.signal;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.TreeMap; import java.util.TreeMap;
@ -79,7 +80,7 @@ public class SignalOmemoStoreConnector
public IdentityKeyPair getIdentityKeyPair() { public IdentityKeyPair getIdentityKeyPair() {
try { try {
return omemoStore.loadOmemoIdentityKeyPair(getOurDevice()); return omemoStore.loadOmemoIdentityKeyPair(getOurDevice());
} catch (CorruptedOmemoKeyException e) { } catch (CorruptedOmemoKeyException | IOException e) {
LOGGER.log(Level.SEVERE, "IdentityKeyPair seems to be invalid.", e); LOGGER.log(Level.SEVERE, "IdentityKeyPair seems to be invalid.", e);
return null; return null;
} }
@ -103,7 +104,11 @@ public class SignalOmemoStoreConnector
throw new AssertionError(e); throw new AssertionError(e);
} }
omemoStore.storeOmemoIdentityKey(getOurDevice(), device, identityKey); try {
omemoStore.storeOmemoIdentityKey(getOurDevice(), device, identityKey);
} catch (IOException e) {
throw new IllegalStateException(e);
}
return true; return true;
} }
@ -118,7 +123,12 @@ public class SignalOmemoStoreConnector
@Override @Override
public PreKeyRecord loadPreKey(int i) throws InvalidKeyIdException { public PreKeyRecord loadPreKey(int i) throws InvalidKeyIdException {
PreKeyRecord preKey = omemoStore.loadOmemoPreKey(getOurDevice(), i); PreKeyRecord preKey;
try {
preKey = omemoStore.loadOmemoPreKey(getOurDevice(), i);
} catch (IOException e) {
throw new IllegalStateException(e);
}
if (preKey == null) { if (preKey == null) {
throw new InvalidKeyIdException("No PreKey with Id " + i + " found."); throw new InvalidKeyIdException("No PreKey with Id " + i + " found.");
@ -129,7 +139,11 @@ public class SignalOmemoStoreConnector
@Override @Override
public void storePreKey(int i, PreKeyRecord preKeyRecord) { public void storePreKey(int i, PreKeyRecord preKeyRecord) {
omemoStore.storeOmemoPreKey(getOurDevice(), i, preKeyRecord); try {
omemoStore.storeOmemoPreKey(getOurDevice(), i, preKeyRecord);
} catch (IOException e) {
throw new IllegalStateException(e);
}
} }
@Override @Override
@ -155,7 +169,12 @@ public class SignalOmemoStoreConnector
throw new AssertionError(e); throw new AssertionError(e);
} }
SessionRecord record = omemoStore.loadRawSession(getOurDevice(), device); SessionRecord record;
try {
record = omemoStore.loadRawSession(getOurDevice(), device);
} catch (IOException e) {
throw new IllegalStateException(e);
}
if (record != null) { if (record != null) {
return record; return record;
@ -173,7 +192,11 @@ public class SignalOmemoStoreConnector
throw new AssertionError(e); throw new AssertionError(e);
} }
return new ArrayList<>(omemoStore.loadAllRawSessionsOf(getOurDevice(), jid).keySet()); try {
return new ArrayList<>(omemoStore.loadAllRawSessionsOf(getOurDevice(), jid).keySet());
} catch (IOException e) {
throw new IllegalStateException(e);
}
} }
@Override @Override
@ -185,7 +208,11 @@ public class SignalOmemoStoreConnector
throw new AssertionError(e); throw new AssertionError(e);
} }
omemoStore.storeRawSession(getOurDevice(), device, sessionRecord); try {
omemoStore.storeRawSession(getOurDevice(), device, sessionRecord);
} catch (IOException e) {
throw new IllegalStateException(e);
}
} }
@Override @Override
@ -226,7 +253,12 @@ public class SignalOmemoStoreConnector
@Override @Override
public SignedPreKeyRecord loadSignedPreKey(int i) throws InvalidKeyIdException { public SignedPreKeyRecord loadSignedPreKey(int i) throws InvalidKeyIdException {
SignedPreKeyRecord signedPreKeyRecord = omemoStore.loadOmemoSignedPreKey(getOurDevice(), i); SignedPreKeyRecord signedPreKeyRecord;
try {
signedPreKeyRecord = omemoStore.loadOmemoSignedPreKey(getOurDevice(), i);
} catch (IOException e) {
throw new IllegalStateException(e);
}
if (signedPreKeyRecord == null) { if (signedPreKeyRecord == null) {
throw new InvalidKeyIdException("No signed preKey with id " + i + " found."); throw new InvalidKeyIdException("No signed preKey with id " + i + " found.");
} }
@ -236,14 +268,22 @@ public class SignalOmemoStoreConnector
@Override @Override
public List<SignedPreKeyRecord> loadSignedPreKeys() { public List<SignedPreKeyRecord> loadSignedPreKeys() {
TreeMap<Integer, SignedPreKeyRecord> signedPreKeyRecordHashMap = TreeMap<Integer, SignedPreKeyRecord> signedPreKeyRecordHashMap;
omemoStore.loadOmemoSignedPreKeys(getOurDevice()); try {
signedPreKeyRecordHashMap = omemoStore.loadOmemoSignedPreKeys(getOurDevice());
} catch (IOException e) {
throw new IllegalStateException(e);
}
return new ArrayList<>(signedPreKeyRecordHashMap.values()); return new ArrayList<>(signedPreKeyRecordHashMap.values());
} }
@Override @Override
public void storeSignedPreKey(int i, SignedPreKeyRecord signedPreKeyRecord) { public void storeSignedPreKey(int i, SignedPreKeyRecord signedPreKeyRecord) {
omemoStore.storeOmemoSignedPreKey(getOurDevice(), i, signedPreKeyRecord); try {
omemoStore.storeOmemoSignedPreKey(getOurDevice(), i, signedPreKeyRecord);
} catch (IOException e) {
throw new IllegalStateException(e);
}
} }
@Override @Override

View File

@ -16,6 +16,7 @@
*/ */
package org.jivesoftware.smackx.omemo; package org.jivesoftware.smackx.omemo;
import java.io.IOException;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.SortedSet; import java.util.SortedSet;
@ -80,7 +81,7 @@ public class CachingOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Se
@Override @Override
public T_IdKeyPair loadOmemoIdentityKeyPair(OmemoDevice userDevice) public T_IdKeyPair loadOmemoIdentityKeyPair(OmemoDevice userDevice)
throws CorruptedOmemoKeyException { throws CorruptedOmemoKeyException, IOException {
T_IdKeyPair pair = getCache(userDevice).identityKeyPair; T_IdKeyPair pair = getCache(userDevice).identityKeyPair;
if (pair == null && persistent != null) { if (pair == null && persistent != null) {
@ -94,7 +95,7 @@ public class CachingOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Se
} }
@Override @Override
public void storeOmemoIdentityKeyPair(OmemoDevice userDevice, T_IdKeyPair identityKeyPair) { public void storeOmemoIdentityKeyPair(OmemoDevice userDevice, T_IdKeyPair identityKeyPair) throws IOException {
getCache(userDevice).identityKeyPair = identityKeyPair; getCache(userDevice).identityKeyPair = identityKeyPair;
if (persistent != null) { if (persistent != null) {
persistent.storeOmemoIdentityKeyPair(userDevice, identityKeyPair); persistent.storeOmemoIdentityKeyPair(userDevice, identityKeyPair);
@ -111,7 +112,7 @@ public class CachingOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Se
@Override @Override
public T_IdKey loadOmemoIdentityKey(OmemoDevice userDevice, OmemoDevice contactsDevice) public T_IdKey loadOmemoIdentityKey(OmemoDevice userDevice, OmemoDevice contactsDevice)
throws CorruptedOmemoKeyException { throws CorruptedOmemoKeyException, IOException {
T_IdKey idKey = getCache(userDevice).identityKeys.get(contactsDevice); T_IdKey idKey = getCache(userDevice).identityKeys.get(contactsDevice);
if (idKey == null && persistent != null) { if (idKey == null && persistent != null) {
@ -125,7 +126,7 @@ public class CachingOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Se
} }
@Override @Override
public void storeOmemoIdentityKey(OmemoDevice userDevice, OmemoDevice device, T_IdKey t_idKey) { public void storeOmemoIdentityKey(OmemoDevice userDevice, OmemoDevice device, T_IdKey t_idKey) throws IOException {
getCache(userDevice).identityKeys.put(device, t_idKey); getCache(userDevice).identityKeys.put(device, t_idKey);
if (persistent != null) { if (persistent != null) {
persistent.storeOmemoIdentityKey(userDevice, device, t_idKey); persistent.storeOmemoIdentityKey(userDevice, device, t_idKey);
@ -141,7 +142,7 @@ public class CachingOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Se
} }
@Override @Override
public void storeOmemoMessageCounter(OmemoDevice userDevice, OmemoDevice contactsDevice, int counter) { public void storeOmemoMessageCounter(OmemoDevice userDevice, OmemoDevice contactsDevice, int counter) throws IOException {
getCache(userDevice).messageCounters.put(contactsDevice, counter); getCache(userDevice).messageCounters.put(contactsDevice, counter);
if (persistent != null) { if (persistent != null) {
persistent.storeOmemoMessageCounter(userDevice, contactsDevice, counter); persistent.storeOmemoMessageCounter(userDevice, contactsDevice, counter);
@ -149,7 +150,7 @@ public class CachingOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Se
} }
@Override @Override
public int loadOmemoMessageCounter(OmemoDevice userDevice, OmemoDevice contactsDevice) { public int loadOmemoMessageCounter(OmemoDevice userDevice, OmemoDevice contactsDevice) throws IOException {
Integer counter = getCache(userDevice).messageCounters.get(contactsDevice); Integer counter = getCache(userDevice).messageCounters.get(contactsDevice);
if (counter == null && persistent != null) { if (counter == null && persistent != null) {
counter = persistent.loadOmemoMessageCounter(userDevice, contactsDevice); counter = persistent.loadOmemoMessageCounter(userDevice, contactsDevice);
@ -165,7 +166,7 @@ public class CachingOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Se
} }
@Override @Override
public void setDateOfLastReceivedMessage(OmemoDevice userDevice, OmemoDevice from, Date date) { public void setDateOfLastReceivedMessage(OmemoDevice userDevice, OmemoDevice from, Date date) throws IOException {
getCache(userDevice).lastMessagesDates.put(from, date); getCache(userDevice).lastMessagesDates.put(from, date);
if (persistent != null) { if (persistent != null) {
persistent.setDateOfLastReceivedMessage(userDevice, from, date); persistent.setDateOfLastReceivedMessage(userDevice, from, date);
@ -173,7 +174,7 @@ public class CachingOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Se
} }
@Override @Override
public Date getDateOfLastReceivedMessage(OmemoDevice userDevice, OmemoDevice from) { public Date getDateOfLastReceivedMessage(OmemoDevice userDevice, OmemoDevice from) throws IOException {
Date last = getCache(userDevice).lastMessagesDates.get(from); Date last = getCache(userDevice).lastMessagesDates.get(from);
if (last == null && persistent != null) { if (last == null && persistent != null) {
@ -187,7 +188,7 @@ public class CachingOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Se
} }
@Override @Override
public void setDateOfLastDeviceIdPublication(OmemoDevice userDevice, OmemoDevice contactsDevice, Date date) { public void setDateOfLastDeviceIdPublication(OmemoDevice userDevice, OmemoDevice contactsDevice, Date date) throws IOException {
getCache(userDevice).lastDeviceIdPublicationDates.put(contactsDevice, date); getCache(userDevice).lastDeviceIdPublicationDates.put(contactsDevice, date);
if (persistent != null) { if (persistent != null) {
persistent.setDateOfLastReceivedMessage(userDevice, contactsDevice, date); persistent.setDateOfLastReceivedMessage(userDevice, contactsDevice, date);
@ -195,7 +196,7 @@ public class CachingOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Se
} }
@Override @Override
public Date getDateOfLastDeviceIdPublication(OmemoDevice userDevice, OmemoDevice contactsDevice) { public Date getDateOfLastDeviceIdPublication(OmemoDevice userDevice, OmemoDevice contactsDevice) throws IOException {
Date last = getCache(userDevice).lastDeviceIdPublicationDates.get(contactsDevice); Date last = getCache(userDevice).lastDeviceIdPublicationDates.get(contactsDevice);
if (last == null && persistent != null) { if (last == null && persistent != null) {
@ -209,7 +210,7 @@ public class CachingOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Se
} }
@Override @Override
public void setDateOfLastSignedPreKeyRenewal(OmemoDevice userDevice, Date date) { public void setDateOfLastSignedPreKeyRenewal(OmemoDevice userDevice, Date date) throws IOException {
getCache(userDevice).lastRenewalDate = date; getCache(userDevice).lastRenewalDate = date;
if (persistent != null) { if (persistent != null) {
persistent.setDateOfLastSignedPreKeyRenewal(userDevice, date); persistent.setDateOfLastSignedPreKeyRenewal(userDevice, date);
@ -217,7 +218,7 @@ public class CachingOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Se
} }
@Override @Override
public Date getDateOfLastSignedPreKeyRenewal(OmemoDevice userDevice) { public Date getDateOfLastSignedPreKeyRenewal(OmemoDevice userDevice) throws IOException {
Date lastRenewal = getCache(userDevice).lastRenewalDate; Date lastRenewal = getCache(userDevice).lastRenewalDate;
if (lastRenewal == null && persistent != null) { if (lastRenewal == null && persistent != null) {
@ -231,7 +232,7 @@ public class CachingOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Se
} }
@Override @Override
public T_PreKey loadOmemoPreKey(OmemoDevice userDevice, int preKeyId) { public T_PreKey loadOmemoPreKey(OmemoDevice userDevice, int preKeyId) throws IOException {
T_PreKey preKey = getCache(userDevice).preKeys.get(preKeyId); T_PreKey preKey = getCache(userDevice).preKeys.get(preKeyId);
if (preKey == null && persistent != null) { if (preKey == null && persistent != null) {
@ -245,7 +246,7 @@ public class CachingOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Se
} }
@Override @Override
public void storeOmemoPreKey(OmemoDevice userDevice, int preKeyId, T_PreKey t_preKey) { public void storeOmemoPreKey(OmemoDevice userDevice, int preKeyId, T_PreKey t_preKey) throws IOException {
getCache(userDevice).preKeys.put(preKeyId, t_preKey); getCache(userDevice).preKeys.put(preKeyId, t_preKey);
if (persistent != null) { if (persistent != null) {
persistent.storeOmemoPreKey(userDevice, preKeyId, t_preKey); persistent.storeOmemoPreKey(userDevice, preKeyId, t_preKey);
@ -261,7 +262,7 @@ public class CachingOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Se
} }
@Override @Override
public TreeMap<Integer, T_PreKey> loadOmemoPreKeys(OmemoDevice userDevice) { public TreeMap<Integer, T_PreKey> loadOmemoPreKeys(OmemoDevice userDevice) throws IOException {
TreeMap<Integer, T_PreKey> preKeys = getCache(userDevice).preKeys; TreeMap<Integer, T_PreKey> preKeys = getCache(userDevice).preKeys;
if (preKeys.isEmpty() && persistent != null) { if (preKeys.isEmpty() && persistent != null) {
@ -272,7 +273,7 @@ public class CachingOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Se
} }
@Override @Override
public T_SigPreKey loadOmemoSignedPreKey(OmemoDevice userDevice, int signedPreKeyId) { public T_SigPreKey loadOmemoSignedPreKey(OmemoDevice userDevice, int signedPreKeyId) throws IOException {
T_SigPreKey sigPreKey = getCache(userDevice).signedPreKeys.get(signedPreKeyId); T_SigPreKey sigPreKey = getCache(userDevice).signedPreKeys.get(signedPreKeyId);
if (sigPreKey == null && persistent != null) { if (sigPreKey == null && persistent != null) {
@ -286,7 +287,7 @@ public class CachingOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Se
} }
@Override @Override
public TreeMap<Integer, T_SigPreKey> loadOmemoSignedPreKeys(OmemoDevice userDevice) { public TreeMap<Integer, T_SigPreKey> loadOmemoSignedPreKeys(OmemoDevice userDevice) throws IOException {
TreeMap<Integer, T_SigPreKey> sigPreKeys = getCache(userDevice).signedPreKeys; TreeMap<Integer, T_SigPreKey> sigPreKeys = getCache(userDevice).signedPreKeys;
if (sigPreKeys.isEmpty() && persistent != null) { if (sigPreKeys.isEmpty() && persistent != null) {
@ -299,7 +300,7 @@ public class CachingOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Se
@Override @Override
public void storeOmemoSignedPreKey(OmemoDevice userDevice, public void storeOmemoSignedPreKey(OmemoDevice userDevice,
int signedPreKeyId, int signedPreKeyId,
T_SigPreKey signedPreKey) { T_SigPreKey signedPreKey) throws IOException {
getCache(userDevice).signedPreKeys.put(signedPreKeyId, signedPreKey); getCache(userDevice).signedPreKeys.put(signedPreKeyId, signedPreKey);
if (persistent != null) { if (persistent != null) {
persistent.storeOmemoSignedPreKey(userDevice, signedPreKeyId, signedPreKey); persistent.storeOmemoSignedPreKey(userDevice, signedPreKeyId, signedPreKey);
@ -315,7 +316,7 @@ public class CachingOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Se
} }
@Override @Override
public T_Sess loadRawSession(OmemoDevice userDevice, OmemoDevice contactsDevice) { public T_Sess loadRawSession(OmemoDevice userDevice, OmemoDevice contactsDevice) throws IOException {
HashMap<Integer, T_Sess> contactSessions = getCache(userDevice).sessions.get(contactsDevice.getJid()); HashMap<Integer, T_Sess> contactSessions = getCache(userDevice).sessions.get(contactsDevice.getJid());
if (contactSessions == null) { if (contactSessions == null) {
contactSessions = new HashMap<>(); contactSessions = new HashMap<>();
@ -334,7 +335,7 @@ public class CachingOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Se
} }
@Override @Override
public HashMap<Integer, T_Sess> loadAllRawSessionsOf(OmemoDevice userDevice, BareJid contact) { public HashMap<Integer, T_Sess> loadAllRawSessionsOf(OmemoDevice userDevice, BareJid contact) throws IOException {
HashMap<Integer, T_Sess> sessions = getCache(userDevice).sessions.get(contact); HashMap<Integer, T_Sess> sessions = getCache(userDevice).sessions.get(contact);
if (sessions == null) { if (sessions == null) {
sessions = new HashMap<>(); sessions = new HashMap<>();
@ -349,7 +350,7 @@ public class CachingOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Se
} }
@Override @Override
public void storeRawSession(OmemoDevice userDevice, OmemoDevice contactsDevicece, T_Sess session) { public void storeRawSession(OmemoDevice userDevice, OmemoDevice contactsDevicece, T_Sess session) throws IOException {
HashMap<Integer, T_Sess> sessions = getCache(userDevice).sessions.get(contactsDevicece.getJid()); HashMap<Integer, T_Sess> sessions = getCache(userDevice).sessions.get(contactsDevicece.getJid());
if (sessions == null) { if (sessions == null) {
sessions = new HashMap<>(); sessions = new HashMap<>();
@ -391,7 +392,7 @@ public class CachingOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Se
} }
@Override @Override
public OmemoCachedDeviceList loadCachedDeviceList(OmemoDevice userDevice, BareJid contact) { public OmemoCachedDeviceList loadCachedDeviceList(OmemoDevice userDevice, BareJid contact) throws IOException {
OmemoCachedDeviceList list = getCache(userDevice).deviceLists.get(contact); OmemoCachedDeviceList list = getCache(userDevice).deviceLists.get(contact);
if (list == null && persistent != null) { if (list == null && persistent != null) {
@ -407,7 +408,7 @@ public class CachingOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_Se
@Override @Override
public void storeCachedDeviceList(OmemoDevice userDevice, public void storeCachedDeviceList(OmemoDevice userDevice,
BareJid contact, BareJid contact,
OmemoCachedDeviceList deviceList) { OmemoCachedDeviceList deviceList) throws IOException {
getCache(userDevice).deviceLists.put(contact, new OmemoCachedDeviceList(deviceList)); getCache(userDevice).deviceLists.put(contact, new OmemoCachedDeviceList(deviceList));
if (persistent != null) { if (persistent != null) {

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright 2017 Paul Schaub * Copyright 2017 Paul Schaub, 2019 Florian Schmaus.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -21,7 +21,6 @@ import java.io.DataOutputStream;
import java.io.EOFException; import java.io.EOFException;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.Collections; import java.util.Collections;
@ -36,7 +35,6 @@ import java.util.TreeSet;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import org.jivesoftware.smack.util.CloseableUtil;
import org.jivesoftware.smack.util.stringencoder.BareJidEncoder; import org.jivesoftware.smack.util.stringencoder.BareJidEncoder;
import org.jivesoftware.smackx.omemo.exceptions.CorruptedOmemoKeyException; import org.jivesoftware.smackx.omemo.exceptions.CorruptedOmemoKeyException;
@ -67,13 +65,13 @@ public abstract class FileBasedOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigP
@Override @Override
public T_IdKeyPair loadOmemoIdentityKeyPair(OmemoDevice userDevice) public T_IdKeyPair loadOmemoIdentityKeyPair(OmemoDevice userDevice)
throws CorruptedOmemoKeyException { throws CorruptedOmemoKeyException, IOException {
File identityKeyPairPath = hierarchy.getIdentityKeyPairPath(userDevice); File identityKeyPairPath = hierarchy.getIdentityKeyPairPath(userDevice);
return keyUtil().identityKeyPairFromBytes(readBytes(identityKeyPairPath)); return keyUtil().identityKeyPairFromBytes(readBytes(identityKeyPairPath));
} }
@Override @Override
public void storeOmemoIdentityKeyPair(OmemoDevice userDevice, T_IdKeyPair identityKeyPair) { public void storeOmemoIdentityKeyPair(OmemoDevice userDevice, T_IdKeyPair identityKeyPair) throws IOException {
File identityKeyPairPath = hierarchy.getIdentityKeyPairPath(userDevice); File identityKeyPairPath = hierarchy.getIdentityKeyPairPath(userDevice);
writeBytes(identityKeyPairPath, keyUtil().identityKeyPairToBytes(identityKeyPair)); writeBytes(identityKeyPairPath, keyUtil().identityKeyPairToBytes(identityKeyPair));
} }
@ -88,14 +86,14 @@ public abstract class FileBasedOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigP
@Override @Override
public T_IdKey loadOmemoIdentityKey(OmemoDevice userDevice, OmemoDevice contactsDevice) public T_IdKey loadOmemoIdentityKey(OmemoDevice userDevice, OmemoDevice contactsDevice)
throws CorruptedOmemoKeyException { throws CorruptedOmemoKeyException, IOException {
File identityKeyPath = hierarchy.getContactsIdentityKeyPath(userDevice, contactsDevice); File identityKeyPath = hierarchy.getContactsIdentityKeyPath(userDevice, contactsDevice);
byte[] bytes = readBytes(identityKeyPath); byte[] bytes = readBytes(identityKeyPath);
return bytes != null ? keyUtil().identityKeyFromBytes(bytes) : null; return bytes != null ? keyUtil().identityKeyFromBytes(bytes) : null;
} }
@Override @Override
public void storeOmemoIdentityKey(OmemoDevice userDevice, OmemoDevice contactsDevice, T_IdKey t_idKey) { public void storeOmemoIdentityKey(OmemoDevice userDevice, OmemoDevice contactsDevice, T_IdKey t_idKey) throws IOException {
File identityKeyPath = hierarchy.getContactsIdentityKeyPath(userDevice, contactsDevice); File identityKeyPath = hierarchy.getContactsIdentityKeyPath(userDevice, contactsDevice);
writeBytes(identityKeyPath, keyUtil().identityKeyToBytes(t_idKey)); writeBytes(identityKeyPath, keyUtil().identityKeyToBytes(t_idKey));
} }
@ -126,46 +124,46 @@ public abstract class FileBasedOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigP
} }
@Override @Override
public void setDateOfLastReceivedMessage(OmemoDevice userDevice, OmemoDevice contactsDevice, Date date) { public void setDateOfLastReceivedMessage(OmemoDevice userDevice, OmemoDevice contactsDevice, Date date) throws IOException {
File lastMessageReceived = hierarchy.getLastMessageReceivedDatePath(userDevice, contactsDevice); File lastMessageReceived = hierarchy.getLastMessageReceivedDatePath(userDevice, contactsDevice);
writeLong(lastMessageReceived, date.getTime()); writeLong(lastMessageReceived, date.getTime());
} }
@Override @Override
public Date getDateOfLastReceivedMessage(OmemoDevice userDevice, OmemoDevice contactsDevice) { public Date getDateOfLastReceivedMessage(OmemoDevice userDevice, OmemoDevice contactsDevice) throws IOException {
File lastMessageReceived = hierarchy.getLastMessageReceivedDatePath(userDevice, contactsDevice); File lastMessageReceived = hierarchy.getLastMessageReceivedDatePath(userDevice, contactsDevice);
Long date = readLong(lastMessageReceived); Long date = readLong(lastMessageReceived);
return date != null ? new Date(date) : null; return date != null ? new Date(date) : null;
} }
@Override @Override
public void setDateOfLastDeviceIdPublication(OmemoDevice userDevice, OmemoDevice contactsDevice, Date date) { public void setDateOfLastDeviceIdPublication(OmemoDevice userDevice, OmemoDevice contactsDevice, Date date) throws IOException {
File lastDeviceIdPublished = hierarchy.getLastDeviceIdPublicationDatePath(userDevice, contactsDevice); File lastDeviceIdPublished = hierarchy.getLastDeviceIdPublicationDatePath(userDevice, contactsDevice);
writeLong(lastDeviceIdPublished, date.getTime()); writeLong(lastDeviceIdPublished, date.getTime());
} }
@Override @Override
public Date getDateOfLastDeviceIdPublication(OmemoDevice userDevice, OmemoDevice contactsDevice) { public Date getDateOfLastDeviceIdPublication(OmemoDevice userDevice, OmemoDevice contactsDevice) throws IOException {
File lastDeviceIdPublished = hierarchy.getLastDeviceIdPublicationDatePath(userDevice, contactsDevice); File lastDeviceIdPublished = hierarchy.getLastDeviceIdPublicationDatePath(userDevice, contactsDevice);
Long date = readLong(lastDeviceIdPublished); Long date = readLong(lastDeviceIdPublished);
return date != null ? new Date(date) : null; return date != null ? new Date(date) : null;
} }
@Override @Override
public void setDateOfLastSignedPreKeyRenewal(OmemoDevice userDevice, Date date) { public void setDateOfLastSignedPreKeyRenewal(OmemoDevice userDevice, Date date) throws IOException {
File lastSignedPreKeyRenewal = hierarchy.getLastSignedPreKeyRenewal(userDevice); File lastSignedPreKeyRenewal = hierarchy.getLastSignedPreKeyRenewal(userDevice);
writeLong(lastSignedPreKeyRenewal, date.getTime()); writeLong(lastSignedPreKeyRenewal, date.getTime());
} }
@Override @Override
public Date getDateOfLastSignedPreKeyRenewal(OmemoDevice userDevice) { public Date getDateOfLastSignedPreKeyRenewal(OmemoDevice userDevice) throws IOException {
File lastSignedPreKeyRenewal = hierarchy.getLastSignedPreKeyRenewal(userDevice); File lastSignedPreKeyRenewal = hierarchy.getLastSignedPreKeyRenewal(userDevice);
Long date = readLong(lastSignedPreKeyRenewal); Long date = readLong(lastSignedPreKeyRenewal);
return date != null ? new Date(date) : null; return date != null ? new Date(date) : null;
} }
@Override @Override
public T_PreKey loadOmemoPreKey(OmemoDevice userDevice, int preKeyId) { public T_PreKey loadOmemoPreKey(OmemoDevice userDevice, int preKeyId) throws IOException {
File preKeyPath = hierarchy.getPreKeyPath(userDevice, preKeyId); File preKeyPath = hierarchy.getPreKeyPath(userDevice, preKeyId);
byte[] bytes = readBytes(preKeyPath); byte[] bytes = readBytes(preKeyPath);
@ -181,7 +179,7 @@ public abstract class FileBasedOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigP
} }
@Override @Override
public void storeOmemoPreKey(OmemoDevice userDevice, int preKeyId, T_PreKey t_preKey) { public void storeOmemoPreKey(OmemoDevice userDevice, int preKeyId, T_PreKey t_preKey) throws IOException {
File preKeyPath = hierarchy.getPreKeyPath(userDevice, preKeyId); File preKeyPath = hierarchy.getPreKeyPath(userDevice, preKeyId);
writeBytes(preKeyPath, keyUtil().preKeyToBytes(t_preKey)); writeBytes(preKeyPath, keyUtil().preKeyToBytes(t_preKey));
} }
@ -195,7 +193,7 @@ public abstract class FileBasedOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigP
} }
@Override @Override
public TreeMap<Integer, T_PreKey> loadOmemoPreKeys(OmemoDevice userDevice) { public TreeMap<Integer, T_PreKey> loadOmemoPreKeys(OmemoDevice userDevice) throws IOException {
File preKeyDirectory = hierarchy.getPreKeysDirectory(userDevice); File preKeyDirectory = hierarchy.getPreKeysDirectory(userDevice);
TreeMap<Integer, T_PreKey> preKeys = new TreeMap<>(); TreeMap<Integer, T_PreKey> preKeys = new TreeMap<>();
@ -221,7 +219,7 @@ public abstract class FileBasedOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigP
} }
@Override @Override
public T_SigPreKey loadOmemoSignedPreKey(OmemoDevice userDevice, int signedPreKeyId) { public T_SigPreKey loadOmemoSignedPreKey(OmemoDevice userDevice, int signedPreKeyId) throws IOException {
File signedPreKeyPath = new File(hierarchy.getSignedPreKeysDirectory(userDevice), Integer.toString(signedPreKeyId)); File signedPreKeyPath = new File(hierarchy.getSignedPreKeysDirectory(userDevice), Integer.toString(signedPreKeyId));
byte[] bytes = readBytes(signedPreKeyPath); byte[] bytes = readBytes(signedPreKeyPath);
if (bytes != null) { if (bytes != null) {
@ -235,7 +233,7 @@ public abstract class FileBasedOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigP
} }
@Override @Override
public TreeMap<Integer, T_SigPreKey> loadOmemoSignedPreKeys(OmemoDevice userDevice) { public TreeMap<Integer, T_SigPreKey> loadOmemoSignedPreKeys(OmemoDevice userDevice) throws IOException {
File signedPreKeysDirectory = hierarchy.getSignedPreKeysDirectory(userDevice); File signedPreKeysDirectory = hierarchy.getSignedPreKeysDirectory(userDevice);
TreeMap<Integer, T_SigPreKey> signedPreKeys = new TreeMap<>(); TreeMap<Integer, T_SigPreKey> signedPreKeys = new TreeMap<>();
@ -263,7 +261,7 @@ public abstract class FileBasedOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigP
@Override @Override
public void storeOmemoSignedPreKey(OmemoDevice userDevice, public void storeOmemoSignedPreKey(OmemoDevice userDevice,
int signedPreKeyId, int signedPreKeyId,
T_SigPreKey signedPreKey) { T_SigPreKey signedPreKey) throws IOException {
File signedPreKeyPath = new File(hierarchy.getSignedPreKeysDirectory(userDevice), Integer.toString(signedPreKeyId)); File signedPreKeyPath = new File(hierarchy.getSignedPreKeysDirectory(userDevice), Integer.toString(signedPreKeyId));
writeBytes(signedPreKeyPath, keyUtil().signedPreKeyToBytes(signedPreKey)); writeBytes(signedPreKeyPath, keyUtil().signedPreKeyToBytes(signedPreKey));
} }
@ -277,7 +275,7 @@ public abstract class FileBasedOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigP
} }
@Override @Override
public T_Sess loadRawSession(OmemoDevice userDevice, OmemoDevice contactsDevice) { public T_Sess loadRawSession(OmemoDevice userDevice, OmemoDevice contactsDevice) throws IOException {
File sessionPath = hierarchy.getContactsSessionPath(userDevice, contactsDevice); File sessionPath = hierarchy.getContactsSessionPath(userDevice, contactsDevice);
byte[] bytes = readBytes(sessionPath); byte[] bytes = readBytes(sessionPath);
if (bytes != null) { if (bytes != null) {
@ -291,7 +289,7 @@ public abstract class FileBasedOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigP
} }
@Override @Override
public HashMap<Integer, T_Sess> loadAllRawSessionsOf(OmemoDevice userDevice, BareJid contact) { public HashMap<Integer, T_Sess> loadAllRawSessionsOf(OmemoDevice userDevice, BareJid contact) throws IOException {
File contactsDirectory = hierarchy.getContactsDir(userDevice, contact); File contactsDirectory = hierarchy.getContactsDir(userDevice, contact);
HashMap<Integer, T_Sess> sessions = new HashMap<>(); HashMap<Integer, T_Sess> sessions = new HashMap<>();
String[] devices = contactsDirectory.list(); String[] devices = contactsDirectory.list();
@ -322,7 +320,7 @@ public abstract class FileBasedOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigP
} }
@Override @Override
public void storeRawSession(OmemoDevice userDevice, OmemoDevice contactsDevice, T_Sess session) { public void storeRawSession(OmemoDevice userDevice, OmemoDevice contactsDevice, T_Sess session) throws IOException {
File sessionPath = hierarchy.getContactsSessionPath(userDevice, contactsDevice); File sessionPath = hierarchy.getContactsSessionPath(userDevice, contactsDevice);
writeBytes(sessionPath, keyUtil().rawSessionToBytes(session)); writeBytes(sessionPath, keyUtil().rawSessionToBytes(session));
} }
@ -357,13 +355,13 @@ public abstract class FileBasedOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigP
} }
@Override @Override
public void storeOmemoMessageCounter(OmemoDevice userDevice, OmemoDevice contactsDevice, int counter) { public void storeOmemoMessageCounter(OmemoDevice userDevice, OmemoDevice contactsDevice, int counter) throws IOException {
File messageCounterFile = hierarchy.getDevicesMessageCounterPath(userDevice, contactsDevice); File messageCounterFile = hierarchy.getDevicesMessageCounterPath(userDevice, contactsDevice);
writeIntegers(messageCounterFile, Collections.singleton(counter)); writeIntegers(messageCounterFile, Collections.singleton(counter));
} }
@Override @Override
public int loadOmemoMessageCounter(OmemoDevice userDevice, OmemoDevice contactsDevice) { public int loadOmemoMessageCounter(OmemoDevice userDevice, OmemoDevice contactsDevice) throws IOException {
File messageCounterFile = hierarchy.getDevicesMessageCounterPath(userDevice, contactsDevice); File messageCounterFile = hierarchy.getDevicesMessageCounterPath(userDevice, contactsDevice);
Set<Integer> integers = readIntegers(messageCounterFile); Set<Integer> integers = readIntegers(messageCounterFile);
@ -375,7 +373,7 @@ public abstract class FileBasedOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigP
} }
@Override @Override
public OmemoCachedDeviceList loadCachedDeviceList(OmemoDevice userDevice, BareJid contact) { public OmemoCachedDeviceList loadCachedDeviceList(OmemoDevice userDevice, BareJid contact) throws IOException {
OmemoCachedDeviceList cachedDeviceList = new OmemoCachedDeviceList(); OmemoCachedDeviceList cachedDeviceList = new OmemoCachedDeviceList();
if (contact == null) { if (contact == null) {
@ -402,7 +400,7 @@ public abstract class FileBasedOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigP
@Override @Override
public void storeCachedDeviceList(OmemoDevice userDevice, public void storeCachedDeviceList(OmemoDevice userDevice,
BareJid contact, BareJid contact,
OmemoCachedDeviceList contactsDeviceList) { OmemoCachedDeviceList contactsDeviceList) throws IOException {
if (contact == null) { if (contact == null) {
return; return;
} }
@ -420,166 +418,7 @@ public abstract class FileBasedOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigP
deleteDirectory(deviceDirectory); deleteDirectory(deviceDirectory);
} }
private static void writeLong(File target, long i) { private static void writeLong(File target, long i) throws IOException {
if (target == null) {
LOGGER.log(Level.WARNING, "Could not write long to null-path.");
return;
}
try {
FileHierarchy.createFile(target);
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Could not create file.", e);
return;
}
DataOutputStream out = null;
try {
out = new DataOutputStream(new FileOutputStream(target));
out.writeLong(i);
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Could not write longs to file.", e);
} finally {
CloseableUtil.maybeClose(out, LOGGER);
}
}
private static Long readLong(File target) {
if (target == null) {
LOGGER.log(Level.WARNING, "Could not read long from null-path.");
return null;
}
Long l;
DataInputStream in = null;
try {
in = new DataInputStream(new FileInputStream(target));
l = in.readLong();
} catch (FileNotFoundException e) {
l = null;
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Could not read long from file.", e);
return null;
} finally {
CloseableUtil.maybeClose(in, LOGGER);
}
return l;
}
private static void writeBytes(File target, byte[] bytes) {
if (target == null) {
LOGGER.log(Level.WARNING, "Could not write bytes to null-path.");
return;
}
// Create file
try {
FileHierarchy.createFile(target);
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Could not create file.", e);
return;
}
DataOutputStream out = null;
try {
out = new DataOutputStream(new FileOutputStream(target));
out.write(bytes);
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Could not write bytes to file.", e);
} finally {
CloseableUtil.maybeClose(out, LOGGER);
}
}
private static byte[] readBytes(File target) {
if (target == null) {
LOGGER.log(Level.WARNING, "Could not read bytes from null-path.");
return null;
}
byte[] b = null;
DataInputStream in = null;
try {
in = new DataInputStream(new FileInputStream(target));
b = new byte[(int) target.length()];
in.read(b);
} catch (FileNotFoundException e) {
b = null;
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Could not read bytes from file.", e);
} finally {
CloseableUtil.maybeClose(in, LOGGER);
}
return b;
}
private static void writeIntegers(File target, Set<Integer> integers) {
if (target == null) {
LOGGER.log(Level.WARNING, "Could not write integers to null-path.");
return;
}
DataOutputStream out = null;
try {
out = new DataOutputStream(new FileOutputStream(target));
for (int i : integers) {
out.writeInt(i);
}
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Could not write integers to file.", e);
} finally {
CloseableUtil.maybeClose(out, LOGGER);
}
}
private static Set<Integer> readIntegers(File target) {
if (target == null) {
LOGGER.log(Level.WARNING, "Could not read integers from null-path.");
return null;
}
HashSet<Integer> integers = new HashSet<>();
DataInputStream in = null;
try {
in = new DataInputStream(new FileInputStream(target));
try {
while (true) {
integers.add(in.readInt());
}
} catch (EOFException e) {
// Reached end of the list.
}
} catch (FileNotFoundException e) {
integers = null;
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Could not read integers.", e);
} finally {
CloseableUtil.maybeClose(in, LOGGER);
}
return integers;
}
/**
* One day... *sheds a tear*
* TODO Use methods below once Smack's minimum Android API level is 19 or higher
*/
/*
private static void writeLong(File target, long i)
throws IOException
{
if (target == null) { if (target == null) {
throw new IOException("Could not write long to null-path."); throw new IOException("Could not write long to null-path.");
} }
@ -591,9 +430,7 @@ public abstract class FileBasedOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigP
} }
} }
private static Long readLong(File target) private static Long readLong(File target) throws IOException {
throws IOException
{
if (target == null) { if (target == null) {
throw new IOException("Could not read long from null-path."); throw new IOException("Could not read long from null-path.");
} }
@ -607,9 +444,7 @@ public abstract class FileBasedOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigP
} }
} }
private static void writeBytes(File target, byte[] bytes) private static void writeBytes(File target, byte[] bytes) throws IOException {
throws IOException
{
if (target == null) { if (target == null) {
throw new IOException("Could not write bytes to null-path."); throw new IOException("Could not write bytes to null-path.");
} }
@ -622,9 +457,7 @@ public abstract class FileBasedOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigP
} }
} }
private static byte[] readBytes(File target) private static byte[] readBytes(File target) throws IOException {
throws IOException
{
if (target == null) { if (target == null) {
throw new IOException("Could not read bytes from null-path."); throw new IOException("Could not read bytes from null-path.");
} }
@ -641,9 +474,7 @@ public abstract class FileBasedOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigP
return b; return b;
} }
private static void writeIntegers(File target, Set<Integer> integers) private static void writeIntegers(File target, Set<Integer> integers) throws IOException {
throws IOException
{
if (target == null) { if (target == null) {
throw new IOException("Could not write integers to null-path."); throw new IOException("Could not write integers to null-path.");
} }
@ -657,9 +488,7 @@ public abstract class FileBasedOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigP
} }
} }
private static Set<Integer> readIntegers(File target) private static Set<Integer> readIntegers(File target) throws IOException {
throws IOException
{
if (target == null) { if (target == null) {
throw new IOException("Could not write integers to null-path."); throw new IOException("Could not write integers to null-path.");
} }
@ -682,7 +511,6 @@ public abstract class FileBasedOmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigP
return integers; return integers;
} }
*/
/** /**
* Delete a directory with all subdirectories. * Delete a directory with all subdirectories.

View File

@ -19,6 +19,7 @@ package org.jivesoftware.smackx.omemo;
import static org.jivesoftware.smackx.omemo.util.OmemoConstants.OMEMO_NAMESPACE_V_AXOLOTL; import static org.jivesoftware.smackx.omemo.util.OmemoConstants.OMEMO_NAMESPACE_V_AXOLOTL;
import static org.jivesoftware.smackx.omemo.util.OmemoConstants.PEP_NODE_DEVICE_LIST_NOTIFY; import static org.jivesoftware.smackx.omemo.util.OmemoConstants.PEP_NODE_DEVICE_LIST_NOTIFY;
import java.io.IOException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -234,11 +235,12 @@ public final class OmemoManager extends Manager {
* @throws XMPPException.XMPPErrorException * @throws XMPPException.XMPPErrorException
* @throws SmackException.NotLoggedInException * @throws SmackException.NotLoggedInException
* @throws PubSubException.NotALeafNodeException * @throws PubSubException.NotALeafNodeException
* @throws IOException
*/ */
public void initialize() public void initialize()
throws SmackException.NotLoggedInException, CorruptedOmemoKeyException, InterruptedException, throws SmackException.NotLoggedInException, CorruptedOmemoKeyException, InterruptedException,
SmackException.NoResponseException, SmackException.NotConnectedException, XMPPException.XMPPErrorException, SmackException.NoResponseException, SmackException.NotConnectedException, XMPPException.XMPPErrorException,
PubSubException.NotALeafNodeException { PubSubException.NotALeafNodeException, IOException {
synchronized (LOCK) { synchronized (LOCK) {
if (!connection().isAuthenticated()) { if (!connection().isAuthenticated()) {
throw new SmackException.NotLoggedInException(); throw new SmackException.NotLoggedInException();
@ -279,8 +281,9 @@ public final class OmemoManager extends Manager {
* @see #requestDeviceListUpdateFor(BareJid) * @see #requestDeviceListUpdateFor(BareJid)
* @param contact contact we want to get a set of device of. * @param contact contact we want to get a set of device of.
* @return set of known devices of that contact. * @return set of known devices of that contact.
* @throws IOException
*/ */
public Set<OmemoDevice> getDevicesOf(BareJid contact) { public Set<OmemoDevice> getDevicesOf(BareJid contact) throws IOException {
OmemoCachedDeviceList list = getOmemoService().getOmemoStoreBackend().loadCachedDeviceList(getOwnDevice(), contact); OmemoCachedDeviceList list = getOmemoService().getOmemoStoreBackend().loadCachedDeviceList(getOwnDevice(), contact);
HashSet<OmemoDevice> devices = new HashSet<>(); HashSet<OmemoDevice> devices = new HashSet<>();
@ -304,11 +307,12 @@ public final class OmemoManager extends Manager {
* @throws SmackException.NotConnectedException * @throws SmackException.NotConnectedException
* @throws SmackException.NoResponseException * @throws SmackException.NoResponseException
* @throws SmackException.NotLoggedInException * @throws SmackException.NotLoggedInException
* @throws IOException
*/ */
public OmemoMessage.Sent encrypt(BareJid recipient, String message) public OmemoMessage.Sent encrypt(BareJid recipient, String message)
throws CryptoFailedException, UndecidedOmemoIdentityException, throws CryptoFailedException, UndecidedOmemoIdentityException,
InterruptedException, SmackException.NotConnectedException, InterruptedException, SmackException.NotConnectedException,
SmackException.NoResponseException, SmackException.NotLoggedInException { SmackException.NoResponseException, SmackException.NotLoggedInException, IOException {
synchronized (LOCK) { synchronized (LOCK) {
Set<BareJid> recipients = new HashSet<>(); Set<BareJid> recipients = new HashSet<>();
recipients.add(recipient); recipients.add(recipient);
@ -328,11 +332,12 @@ public final class OmemoManager extends Manager {
* @throws SmackException.NotConnectedException * @throws SmackException.NotConnectedException
* @throws SmackException.NoResponseException * @throws SmackException.NoResponseException
* @throws SmackException.NotLoggedInException * @throws SmackException.NotLoggedInException
* @throws IOException
*/ */
public OmemoMessage.Sent encrypt(Set<BareJid> recipients, String message) public OmemoMessage.Sent encrypt(Set<BareJid> recipients, String message)
throws CryptoFailedException, UndecidedOmemoIdentityException, throws CryptoFailedException, UndecidedOmemoIdentityException,
InterruptedException, SmackException.NotConnectedException, InterruptedException, SmackException.NotConnectedException,
SmackException.NoResponseException, SmackException.NotLoggedInException { SmackException.NoResponseException, SmackException.NotLoggedInException, IOException {
synchronized (LOCK) { synchronized (LOCK) {
LoggedInOmemoManager guard = new LoggedInOmemoManager(this); LoggedInOmemoManager guard = new LoggedInOmemoManager(this);
Set<OmemoDevice> devices = getDevicesOf(getOwnJid()); Set<OmemoDevice> devices = getDevicesOf(getOwnJid());
@ -357,12 +362,13 @@ public final class OmemoManager extends Manager {
* @throws SmackException.NoResponseException * @throws SmackException.NoResponseException
* @throws NoOmemoSupportException When the muc doesn't support OMEMO. * @throws NoOmemoSupportException When the muc doesn't support OMEMO.
* @throws SmackException.NotLoggedInException * @throws SmackException.NotLoggedInException
* @throws IOException
*/ */
public OmemoMessage.Sent encrypt(MultiUserChat muc, String message) public OmemoMessage.Sent encrypt(MultiUserChat muc, String message)
throws UndecidedOmemoIdentityException, CryptoFailedException, throws UndecidedOmemoIdentityException, CryptoFailedException,
XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException,
SmackException.NoResponseException, NoOmemoSupportException, SmackException.NoResponseException, NoOmemoSupportException,
SmackException.NotLoggedInException { SmackException.NotLoggedInException, IOException {
synchronized (LOCK) { synchronized (LOCK) {
if (!multiUserChatSupportsOmemo(muc)) { if (!multiUserChatSupportsOmemo(muc)) {
throw new NoOmemoSupportException(); throw new NoOmemoSupportException();
@ -390,10 +396,11 @@ public final class OmemoManager extends Manager {
* @throws CorruptedOmemoKeyException if our or their key is corrupted * @throws CorruptedOmemoKeyException if our or their key is corrupted
* @throws NoRawSessionException if the message was not a preKeyMessage, but we had no session with the contact * @throws NoRawSessionException if the message was not a preKeyMessage, but we had no session with the contact
* @throws CryptoFailedException if decryption fails * @throws CryptoFailedException if decryption fails
* @throws IOException
*/ */
public OmemoMessage.Received decrypt(BareJid sender, OmemoElement omemoElement) public OmemoMessage.Received decrypt(BareJid sender, OmemoElement omemoElement)
throws SmackException.NotLoggedInException, CorruptedOmemoKeyException, NoRawSessionException, throws SmackException.NotLoggedInException, CorruptedOmemoKeyException, NoRawSessionException,
CryptoFailedException { CryptoFailedException, IOException {
LoggedInOmemoManager managerGuard = new LoggedInOmemoManager(this); LoggedInOmemoManager managerGuard = new LoggedInOmemoManager(this);
return getOmemoService().decryptMessage(managerGuard, sender, omemoElement); return getOmemoService().decryptMessage(managerGuard, sender, omemoElement);
} }
@ -404,9 +411,10 @@ public final class OmemoManager extends Manager {
* @param mamQuery The MAM query * @param mamQuery The MAM query
* @return list of decrypted OmemoMessages * @return list of decrypted OmemoMessages
* @throws SmackException.NotLoggedInException if the Manager is not authenticated. * @throws SmackException.NotLoggedInException if the Manager is not authenticated.
* @throws IOException
*/ */
public List<MessageOrOmemoMessage> decryptMamQueryResult(MamManager.MamQuery mamQuery) public List<MessageOrOmemoMessage> decryptMamQueryResult(MamManager.MamQuery mamQuery)
throws SmackException.NotLoggedInException { throws SmackException.NotLoggedInException, IOException {
return new ArrayList<>(getOmemoService().decryptMamQueryResult(new LoggedInOmemoManager(this), mamQuery)); return new ArrayList<>(getOmemoService().decryptMamQueryResult(new LoggedInOmemoManager(this), mamQuery));
} }
@ -486,11 +494,12 @@ public final class OmemoManager extends Manager {
* @throws SmackException.NoResponseException * @throws SmackException.NoResponseException
* @throws NoSuchAlgorithmException * @throws NoSuchAlgorithmException
* @throws SmackException.NotConnectedException * @throws SmackException.NotConnectedException
* @throws IOException
*/ */
public void sendRatchetUpdateMessage(OmemoDevice recipient) public void sendRatchetUpdateMessage(OmemoDevice recipient)
throws SmackException.NotLoggedInException, CorruptedOmemoKeyException, InterruptedException, throws SmackException.NotLoggedInException, CorruptedOmemoKeyException, InterruptedException,
SmackException.NoResponseException, NoSuchAlgorithmException, SmackException.NotConnectedException, SmackException.NoResponseException, NoSuchAlgorithmException, SmackException.NotConnectedException,
CryptoFailedException, CannotEstablishOmemoSessionException { CryptoFailedException, CannotEstablishOmemoSessionException, IOException {
synchronized (LOCK) { synchronized (LOCK) {
Message message = new Message(); Message message = new Message();
message.setFrom(getOwnJid()); message.setFrom(getOwnJid());
@ -516,10 +525,11 @@ public final class OmemoManager extends Manager {
* @throws SmackException.NoResponseException * @throws SmackException.NoResponseException
* @throws PubSubException.NotALeafNodeException * @throws PubSubException.NotALeafNodeException
* @throws XMPPException.XMPPErrorException * @throws XMPPException.XMPPErrorException
* @throws IOException
*/ */
public boolean contactSupportsOmemo(BareJid contact) public boolean contactSupportsOmemo(BareJid contact)
throws InterruptedException, PubSubException.NotALeafNodeException, XMPPException.XMPPErrorException, throws InterruptedException, PubSubException.NotALeafNodeException, XMPPException.XMPPErrorException,
SmackException.NotConnectedException, SmackException.NoResponseException { SmackException.NotConnectedException, SmackException.NoResponseException, IOException {
synchronized (LOCK) { synchronized (LOCK) {
OmemoCachedDeviceList deviceList = getOmemoService().refreshDeviceList(connection(), getOwnDevice(), contact); OmemoCachedDeviceList deviceList = getOmemoService().refreshDeviceList(connection(), getOwnDevice(), contact);
return !deviceList.getActiveDevices().isEmpty(); return !deviceList.getActiveDevices().isEmpty();
@ -569,9 +579,10 @@ public final class OmemoManager extends Manager {
* @return fingerprint * @return fingerprint
* @throws SmackException.NotLoggedInException if we don't know our bareJid yet. * @throws SmackException.NotLoggedInException if we don't know our bareJid yet.
* @throws CorruptedOmemoKeyException if our identityKey is corrupted. * @throws CorruptedOmemoKeyException if our identityKey is corrupted.
* @throws IOException
*/ */
public OmemoFingerprint getOwnFingerprint() public OmemoFingerprint getOwnFingerprint()
throws SmackException.NotLoggedInException, CorruptedOmemoKeyException { throws SmackException.NotLoggedInException, CorruptedOmemoKeyException, IOException {
synchronized (LOCK) { synchronized (LOCK) {
if (getOwnJid() == null) { if (getOwnJid() == null) {
throw new SmackException.NotLoggedInException(); throw new SmackException.NotLoggedInException();
@ -591,11 +602,12 @@ public final class OmemoManager extends Manager {
* @throws SmackException.NotConnectedException * @throws SmackException.NotConnectedException
* @throws InterruptedException * @throws InterruptedException
* @throws SmackException.NoResponseException * @throws SmackException.NoResponseException
* @throws IOException
*/ */
public OmemoFingerprint getFingerprint(OmemoDevice device) public OmemoFingerprint getFingerprint(OmemoDevice device)
throws CannotEstablishOmemoSessionException, SmackException.NotLoggedInException, throws CannotEstablishOmemoSessionException, SmackException.NotLoggedInException,
CorruptedOmemoKeyException, SmackException.NotConnectedException, InterruptedException, CorruptedOmemoKeyException, SmackException.NotConnectedException, InterruptedException,
SmackException.NoResponseException { SmackException.NoResponseException, IOException {
synchronized (LOCK) { synchronized (LOCK) {
if (getOwnJid() == null) { if (getOwnJid() == null) {
throw new SmackException.NotLoggedInException(); throw new SmackException.NotLoggedInException();
@ -621,11 +633,12 @@ public final class OmemoManager extends Manager {
* @throws SmackException.NotConnectedException * @throws SmackException.NotConnectedException
* @throws InterruptedException * @throws InterruptedException
* @throws SmackException.NoResponseException * @throws SmackException.NoResponseException
* @throws IOException
*/ */
public HashMap<OmemoDevice, OmemoFingerprint> getActiveFingerprints(BareJid contact) public HashMap<OmemoDevice, OmemoFingerprint> getActiveFingerprints(BareJid contact)
throws SmackException.NotLoggedInException, CorruptedOmemoKeyException, throws SmackException.NotLoggedInException, CorruptedOmemoKeyException,
CannotEstablishOmemoSessionException, SmackException.NotConnectedException, InterruptedException, CannotEstablishOmemoSessionException, SmackException.NotConnectedException, InterruptedException,
SmackException.NoResponseException { SmackException.NoResponseException, IOException {
synchronized (LOCK) { synchronized (LOCK) {
if (getOwnJid() == null) { if (getOwnJid() == null) {
throw new SmackException.NotLoggedInException(); throw new SmackException.NotLoggedInException();
@ -692,10 +705,11 @@ public final class OmemoManager extends Manager {
* @throws XMPPException.XMPPErrorException * @throws XMPPException.XMPPErrorException
* @throws SmackException.NotConnectedException * @throws SmackException.NotConnectedException
* @throws SmackException.NoResponseException * @throws SmackException.NoResponseException
* @throws IOException
*/ */
public void requestDeviceListUpdateFor(BareJid contact) public void requestDeviceListUpdateFor(BareJid contact)
throws InterruptedException, PubSubException.NotALeafNodeException, XMPPException.XMPPErrorException, throws InterruptedException, PubSubException.NotALeafNodeException, XMPPException.XMPPErrorException,
SmackException.NotConnectedException, SmackException.NoResponseException { SmackException.NotConnectedException, SmackException.NoResponseException, IOException {
synchronized (LOCK) { synchronized (LOCK) {
getOmemoService().refreshDeviceList(connection(), getOwnDevice(), contact); getOmemoService().refreshDeviceList(connection(), getOwnDevice(), contact);
} }
@ -709,10 +723,11 @@ public final class OmemoManager extends Manager {
* @throws XMPPException.XMPPErrorException * @throws XMPPException.XMPPErrorException
* @throws SmackException.NotConnectedException * @throws SmackException.NotConnectedException
* @throws SmackException.NoResponseException * @throws SmackException.NoResponseException
* @throws IOException
*/ */
public void purgeDeviceList() public void purgeDeviceList()
throws SmackException.NotLoggedInException, InterruptedException, XMPPException.XMPPErrorException, throws SmackException.NotLoggedInException, InterruptedException, XMPPException.XMPPErrorException,
SmackException.NotConnectedException, SmackException.NoResponseException { SmackException.NotConnectedException, SmackException.NoResponseException, IOException {
synchronized (LOCK) { synchronized (LOCK) {
getOmemoService().purgeDeviceList(new LoggedInOmemoManager(this)); getOmemoService().purgeDeviceList(new LoggedInOmemoManager(this));
} }
@ -729,10 +744,11 @@ public final class OmemoManager extends Manager {
* @throws SmackException.NotConnectedException XMPP error * @throws SmackException.NotConnectedException XMPP error
* @throws SmackException.NoResponseException XMPP error * @throws SmackException.NoResponseException XMPP error
* @throws SmackException.NotLoggedInException * @throws SmackException.NotLoggedInException
* @throws IOException
*/ */
public void rotateSignedPreKey() public void rotateSignedPreKey()
throws CorruptedOmemoKeyException, SmackException.NotLoggedInException, XMPPException.XMPPErrorException, throws CorruptedOmemoKeyException, SmackException.NotLoggedInException, XMPPException.XMPPErrorException,
SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException { SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException, IOException {
synchronized (LOCK) { synchronized (LOCK) {
if (!connection().isAuthenticated()) { if (!connection().isAuthenticated()) {
throw new SmackException.NotLoggedInException(); throw new SmackException.NotLoggedInException();
@ -956,8 +972,8 @@ public final class OmemoManager extends Manager {
try { try {
getOmemoService().onOmemoMessageStanzaReceived(packet, getOmemoService().onOmemoMessageStanzaReceived(packet,
new LoggedInOmemoManager(OmemoManager.this)); new LoggedInOmemoManager(OmemoManager.this));
} catch (SmackException.NotLoggedInException e) { } catch (SmackException.NotLoggedInException | IOException e) {
LOGGER.warning("Received OMEMO stanza while being offline: " + e); LOGGER.log(Level.SEVERE, "Exception while processing OMEMO stanza", e);
} }
} }
}); });
@ -979,8 +995,8 @@ public final class OmemoManager extends Manager {
try { try {
getOmemoService().onOmemoCarbonCopyReceived(direction, carbonCopy, wrappingMessage, getOmemoService().onOmemoCarbonCopyReceived(direction, carbonCopy, wrappingMessage,
new LoggedInOmemoManager(OmemoManager.this)); new LoggedInOmemoManager(OmemoManager.this));
} catch (SmackException.NotLoggedInException e) { } catch (SmackException.NotLoggedInException | IOException e) {
LOGGER.warning("Received OMEMO carbon copy while being offline: " + e); LOGGER.log(Level.SEVERE, "Exception while processing OMEMO stanza", e);
} }
} }
} }
@ -1018,14 +1034,23 @@ public final class OmemoManager extends Manager {
} }
// Device List <list> // Device List <list>
OmemoCachedDeviceList deviceList;
OmemoDeviceListElement receivedDeviceList = (OmemoDeviceListElement) payloadItem.getPayload(); OmemoDeviceListElement receivedDeviceList = (OmemoDeviceListElement) payloadItem.getPayload();
getOmemoService().getOmemoStoreBackend().mergeCachedDeviceList(getOwnDevice(), from, receivedDeviceList); try {
getOmemoService().getOmemoStoreBackend().mergeCachedDeviceList(getOwnDevice(), from,
receivedDeviceList);
if (!from.asBareJid().equals(getOwnJid())) { if (!from.asBareJid().equals(getOwnJid())) {
continue;
}
deviceList = getOmemoService().cleanUpDeviceList(getOwnDevice());
} catch (IOException e) {
LOGGER.log(Level.SEVERE,
"IOException while processing OMEMO PEP device updates. Message: " + message,
e);
continue; continue;
} }
OmemoCachedDeviceList deviceList = getOmemoService().cleanUpDeviceList(getOwnDevice());
final OmemoDeviceListElement_VAxolotl newDeviceList = new OmemoDeviceListElement_VAxolotl(deviceList); final OmemoDeviceListElement_VAxolotl newDeviceList = new OmemoDeviceListElement_VAxolotl(deviceList);
if (!newDeviceList.copyDeviceIds().equals(receivedDeviceList.copyDeviceIds())) { if (!newDeviceList.copyDeviceIds().equals(receivedDeviceList.copyDeviceIds())) {

View File

@ -16,6 +16,7 @@
*/ */
package org.jivesoftware.smackx.omemo; package org.jivesoftware.smackx.omemo;
import java.io.IOException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -65,10 +66,11 @@ public abstract class OmemoRatchet<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
* @throws NoRawSessionException when no double ratchet session was found. * @throws NoRawSessionException when no double ratchet session was found.
* @throws CryptoFailedException * @throws CryptoFailedException
* @throws UntrustedOmemoIdentityException * @throws UntrustedOmemoIdentityException
* @throws IOException
*/ */
public abstract byte[] doubleRatchetDecrypt(OmemoDevice sender, byte[] encryptedKey) public abstract byte[] doubleRatchetDecrypt(OmemoDevice sender, byte[] encryptedKey)
throws CorruptedOmemoKeyException, NoRawSessionException, CryptoFailedException, throws CorruptedOmemoKeyException, NoRawSessionException, CryptoFailedException,
UntrustedOmemoIdentityException; UntrustedOmemoIdentityException, IOException;
/** /**
* Encrypt a messageKey with the double ratchet session of the recipient. * Encrypt a messageKey with the double ratchet session of the recipient.
@ -86,9 +88,10 @@ public abstract class OmemoRatchet<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
* @return tuple of cipher generated from the unpacked message key and the auth-tag * @return tuple of cipher generated from the unpacked message key and the auth-tag
* @throws CryptoFailedException if decryption using the double ratchet fails * @throws CryptoFailedException if decryption using the double ratchet fails
* @throws NoRawSessionException if we have no session, but the element was NOT a PreKeyMessage * @throws NoRawSessionException if we have no session, but the element was NOT a PreKeyMessage
* @throws IOException
*/ */
CipherAndAuthTag retrieveMessageKeyAndAuthTag(OmemoDevice sender, OmemoElement element) throws CryptoFailedException, CipherAndAuthTag retrieveMessageKeyAndAuthTag(OmemoDevice sender, OmemoElement element) throws CryptoFailedException,
NoRawSessionException { NoRawSessionException, IOException {
int keyId = omemoManager.getDeviceId(); int keyId = omemoManager.getDeviceId();
byte[] unpackedKey = null; byte[] unpackedKey = null;
List<CryptoFailedException> decryptExceptions = new ArrayList<>(); List<CryptoFailedException> decryptExceptions = new ArrayList<>();

View File

@ -19,6 +19,7 @@ package org.jivesoftware.smackx.omemo;
import static org.jivesoftware.smackx.omemo.util.OmemoConstants.Crypto.KEYLENGTH; import static org.jivesoftware.smackx.omemo.util.OmemoConstants.Crypto.KEYLENGTH;
import static org.jivesoftware.smackx.omemo.util.OmemoConstants.Crypto.KEYTYPE; import static org.jivesoftware.smackx.omemo.util.OmemoConstants.Crypto.KEYTYPE;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException; import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException; import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
@ -234,11 +235,12 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
* @throws SmackException.NotConnectedException * @throws SmackException.NotConnectedException
* @throws SmackException.NoResponseException * @throws SmackException.NoResponseException
* @throws PubSubException.NotALeafNodeException * @throws PubSubException.NotALeafNodeException
* @throws IOException
*/ */
void init(OmemoManager.LoggedInOmemoManager managerGuard) void init(OmemoManager.LoggedInOmemoManager managerGuard)
throws InterruptedException, CorruptedOmemoKeyException, XMPPException.XMPPErrorException, throws InterruptedException, CorruptedOmemoKeyException, XMPPException.XMPPErrorException,
SmackException.NotConnectedException, SmackException.NoResponseException, SmackException.NotConnectedException, SmackException.NoResponseException,
PubSubException.NotALeafNodeException { PubSubException.NotALeafNodeException, IOException {
OmemoManager manager = managerGuard.get(); OmemoManager manager = managerGuard.get();
OmemoDevice userDevice = manager.getOwnDevice(); OmemoDevice userDevice = manager.getOwnDevice();
@ -273,12 +275,13 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
* @throws CorruptedOmemoKeyException if our IdentityKeyPair is corrupted. * @throws CorruptedOmemoKeyException if our IdentityKeyPair is corrupted.
* @throws SmackException.NotConnectedException * @throws SmackException.NotConnectedException
* @throws CannotEstablishOmemoSessionException if session negotiation fails. * @throws CannotEstablishOmemoSessionException if session negotiation fails.
* @throws IOException
*/ */
OmemoElement createRatchetUpdateElement(OmemoManager.LoggedInOmemoManager managerGuard, OmemoElement createRatchetUpdateElement(OmemoManager.LoggedInOmemoManager managerGuard,
OmemoDevice contactsDevice) OmemoDevice contactsDevice)
throws InterruptedException, SmackException.NoResponseException, CorruptedOmemoKeyException, throws InterruptedException, SmackException.NoResponseException, CorruptedOmemoKeyException,
SmackException.NotConnectedException, CannotEstablishOmemoSessionException, NoSuchAlgorithmException, SmackException.NotConnectedException, CannotEstablishOmemoSessionException, NoSuchAlgorithmException,
CryptoFailedException { CryptoFailedException, IOException {
OmemoManager manager = managerGuard.get(); OmemoManager manager = managerGuard.get();
OmemoDevice userDevice = manager.getOwnDevice(); OmemoDevice userDevice = manager.getOwnDevice();
@ -334,6 +337,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
* @throws SmackException.NoResponseException * @throws SmackException.NoResponseException
* @throws UndecidedOmemoIdentityException if the list of recipient devices contains undecided devices * @throws UndecidedOmemoIdentityException if the list of recipient devices contains undecided devices
* @throws CryptoFailedException if we are lacking some crypto primitives * @throws CryptoFailedException if we are lacking some crypto primitives
* @throws IOException
*/ */
private OmemoMessage.Sent encrypt(OmemoManager.LoggedInOmemoManager managerGuard, private OmemoMessage.Sent encrypt(OmemoManager.LoggedInOmemoManager managerGuard,
Set<OmemoDevice> contactsDevices, Set<OmemoDevice> contactsDevices,
@ -341,7 +345,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
byte[] iv, byte[] iv,
String message) String message)
throws SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException, throws SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException,
UndecidedOmemoIdentityException, CryptoFailedException { UndecidedOmemoIdentityException, CryptoFailedException, IOException {
OmemoManager manager = managerGuard.get(); OmemoManager manager = managerGuard.get();
OmemoDevice userDevice = manager.getOwnDevice(); OmemoDevice userDevice = manager.getOwnDevice();
@ -435,11 +439,12 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
* @throws CorruptedOmemoKeyException if the identityKey of the sender is damaged. * @throws CorruptedOmemoKeyException if the identityKey of the sender is damaged.
* @throws CryptoFailedException if decryption fails. * @throws CryptoFailedException if decryption fails.
* @throws NoRawSessionException if we have no session with the device and it sent a normal (non-preKey) message. * @throws NoRawSessionException if we have no session with the device and it sent a normal (non-preKey) message.
* @throws IOException
*/ */
OmemoMessage.Received decryptMessage(OmemoManager.LoggedInOmemoManager managerGuard, OmemoMessage.Received decryptMessage(OmemoManager.LoggedInOmemoManager managerGuard,
BareJid senderJid, BareJid senderJid,
OmemoElement omemoElement) OmemoElement omemoElement)
throws CorruptedOmemoKeyException, CryptoFailedException, NoRawSessionException { throws CorruptedOmemoKeyException, CryptoFailedException, NoRawSessionException, IOException {
OmemoManager manager = managerGuard.get(); OmemoManager manager = managerGuard.get();
int senderId = omemoElement.getHeader().getSid(); int senderId = omemoElement.getHeader().getSid();
@ -488,13 +493,14 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
* @throws CryptoFailedException if we are lacking some cryptographic algorithms * @throws CryptoFailedException if we are lacking some cryptographic algorithms
* @throws SmackException.NotConnectedException * @throws SmackException.NotConnectedException
* @throws SmackException.NoResponseException * @throws SmackException.NoResponseException
* @throws IOException
*/ */
OmemoMessage.Sent createKeyTransportElement(OmemoManager.LoggedInOmemoManager managerGuard, OmemoMessage.Sent createKeyTransportElement(OmemoManager.LoggedInOmemoManager managerGuard,
Set<OmemoDevice> contactsDevices, Set<OmemoDevice> contactsDevices,
byte[] key, byte[] key,
byte[] iv) byte[] iv)
throws InterruptedException, UndecidedOmemoIdentityException, CryptoFailedException, throws InterruptedException, UndecidedOmemoIdentityException, CryptoFailedException,
SmackException.NotConnectedException, SmackException.NoResponseException { SmackException.NotConnectedException, SmackException.NoResponseException, IOException {
return encrypt(managerGuard, contactsDevices, key, iv, null); return encrypt(managerGuard, contactsDevices, key, iv, null);
} }
@ -511,12 +517,13 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
* @throws CryptoFailedException if we are lacking some cryptographic algorithms * @throws CryptoFailedException if we are lacking some cryptographic algorithms
* @throws SmackException.NotConnectedException * @throws SmackException.NotConnectedException
* @throws SmackException.NoResponseException * @throws SmackException.NoResponseException
* @throws IOException
*/ */
OmemoMessage.Sent createOmemoMessage(OmemoManager.LoggedInOmemoManager managerGuard, OmemoMessage.Sent createOmemoMessage(OmemoManager.LoggedInOmemoManager managerGuard,
Set<OmemoDevice> contactsDevices, Set<OmemoDevice> contactsDevices,
String message) String message)
throws InterruptedException, UndecidedOmemoIdentityException, CryptoFailedException, throws InterruptedException, UndecidedOmemoIdentityException, CryptoFailedException,
SmackException.NotConnectedException, SmackException.NoResponseException { SmackException.NotConnectedException, SmackException.NoResponseException, IOException {
byte[] key, iv; byte[] key, iv;
iv = OmemoMessageBuilder.generateIv(); iv = OmemoMessageBuilder.generateIv();
@ -643,10 +650,11 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
* @throws XMPPException.XMPPErrorException * @throws XMPPException.XMPPErrorException
* @throws SmackException.NotConnectedException * @throws SmackException.NotConnectedException
* @throws SmackException.NoResponseException * @throws SmackException.NoResponseException
* @throws IOException
*/ */
private void refreshAndRepublishDeviceList(XMPPConnection connection, OmemoDevice userDevice) private void refreshAndRepublishDeviceList(XMPPConnection connection, OmemoDevice userDevice)
throws InterruptedException, PubSubException.NotALeafNodeException, XMPPException.XMPPErrorException, throws InterruptedException, PubSubException.NotALeafNodeException, XMPPException.XMPPErrorException,
SmackException.NotConnectedException, SmackException.NoResponseException { SmackException.NotConnectedException, SmackException.NoResponseException, IOException {
// refreshOmemoDeviceList; // refreshOmemoDeviceList;
OmemoDeviceListElement publishedList; OmemoDeviceListElement publishedList;
@ -685,8 +693,9 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
* *
* @param userDevice * @param userDevice
* @return * @return
* @throws IOException
*/ */
OmemoCachedDeviceList cleanUpDeviceList(OmemoDevice userDevice) { OmemoCachedDeviceList cleanUpDeviceList(OmemoDevice userDevice) throws IOException {
OmemoCachedDeviceList cachedDeviceList; OmemoCachedDeviceList cachedDeviceList;
// Delete stale devices if allowed and necessary // Delete stale devices if allowed and necessary
@ -719,10 +728,11 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
* @throws XMPPException.XMPPErrorException * @throws XMPPException.XMPPErrorException
* @throws SmackException.NotConnectedException * @throws SmackException.NotConnectedException
* @throws SmackException.NoResponseException * @throws SmackException.NoResponseException
* @throws IOException
*/ */
OmemoCachedDeviceList refreshDeviceList(XMPPConnection connection, OmemoDevice userDevice, BareJid contact) OmemoCachedDeviceList refreshDeviceList(XMPPConnection connection, OmemoDevice userDevice, BareJid contact)
throws InterruptedException, PubSubException.NotALeafNodeException, XMPPException.XMPPErrorException, throws InterruptedException, PubSubException.NotALeafNodeException, XMPPException.XMPPErrorException,
SmackException.NotConnectedException, SmackException.NoResponseException { SmackException.NotConnectedException, SmackException.NoResponseException, IOException {
// refreshOmemoDeviceList; // refreshOmemoDeviceList;
OmemoDeviceListElement publishedList; OmemoDeviceListElement publishedList;
try { try {
@ -790,11 +800,12 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
* @throws SmackException.NotConnectedException * @throws SmackException.NotConnectedException
* @throws InterruptedException * @throws InterruptedException
* @throws SmackException.NoResponseException * @throws SmackException.NoResponseException
* @throws IOException
*/ */
private Set<OmemoDevice> buildMissingSessionsWithDevices(XMPPConnection connection, private Set<OmemoDevice> buildMissingSessionsWithDevices(XMPPConnection connection,
OmemoDevice userDevice, OmemoDevice userDevice,
Set<OmemoDevice> devices) Set<OmemoDevice> devices)
throws SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException { throws SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException, IOException {
Set<OmemoDevice> devicesWithSession = new HashSet<>(); Set<OmemoDevice> devicesWithSession = new HashSet<>();
for (OmemoDevice device : devices) { for (OmemoDevice device : devices) {
@ -828,8 +839,9 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
* @param callback OmemoTrustCallback to query the trust decisions from * @param callback OmemoTrustCallback to query the trust decisions from
* @param devices set of OmemoDevices * @param devices set of OmemoDevices
* @return set of OmemoDevices which contains all devices from the set devices, which are undecided * @return set of OmemoDevices which contains all devices from the set devices, which are undecided
* @throws IOException
*/ */
private Set<OmemoDevice> getUndecidedDevices(OmemoDevice userDevice, OmemoTrustCallback callback, Set<OmemoDevice> devices) { private Set<OmemoDevice> getUndecidedDevices(OmemoDevice userDevice, OmemoTrustCallback callback, Set<OmemoDevice> devices) throws IOException {
Set<OmemoDevice> undecidedDevices = new HashSet<>(); Set<OmemoDevice> undecidedDevices = new HashSet<>();
for (OmemoDevice device : devices) { for (OmemoDevice device : devices) {
@ -858,8 +870,9 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
* @param userDevice our OmemoDevice. * @param userDevice our OmemoDevice.
* @param contactsDevice OmemoDevice of the contact. * @param contactsDevice OmemoDevice of the contact.
* @return true if userDevice has session with contactsDevice. * @return true if userDevice has session with contactsDevice.
* @throws IOException
*/ */
private boolean hasSession(OmemoDevice userDevice, OmemoDevice contactsDevice) { private boolean hasSession(OmemoDevice userDevice, OmemoDevice contactsDevice) throws IOException {
return getOmemoStoreBackend().loadRawSession(userDevice, contactsDevice) != null; return getOmemoStoreBackend().loadRawSession(userDevice, contactsDevice) != null;
} }
@ -881,8 +894,9 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
* *
* @param userDevice our OmemoDevice * @param userDevice our OmemoDevice
* @return true if rotation is necessary * @return true if rotation is necessary
* @throws IOException
*/ */
private boolean shouldRotateSignedPreKey(OmemoDevice userDevice) { private boolean shouldRotateSignedPreKey(OmemoDevice userDevice) throws IOException {
if (!OmemoConfiguration.getRenewOldSignedPreKeys()) { if (!OmemoConfiguration.getRenewOldSignedPreKeys()) {
return false; return false;
} }
@ -909,8 +923,9 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
* *
* @param userDevice our OmemoDevice * @param userDevice our OmemoDevice
* @return our altered deviceList with stale devices marked as inactive. * @return our altered deviceList with stale devices marked as inactive.
* @throws IOException
*/ */
private OmemoCachedDeviceList deleteStaleDevices(OmemoDevice userDevice) { private OmemoCachedDeviceList deleteStaleDevices(OmemoDevice userDevice) throws IOException {
OmemoCachedDeviceList deviceList = getOmemoStoreBackend().loadCachedDeviceList(userDevice); OmemoCachedDeviceList deviceList = getOmemoStoreBackend().loadCachedDeviceList(userDevice);
int maxAgeHours = OmemoConfiguration.getDeleteStaleDevicesAfterHours(); int maxAgeHours = OmemoConfiguration.getDeleteStaleDevicesAfterHours();
return removeStaleDevicesFromDeviceList(userDevice, userDevice.getJid(), deviceList, maxAgeHours); return removeStaleDevicesFromDeviceList(userDevice, userDevice.getJid(), deviceList, maxAgeHours);
@ -928,11 +943,12 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
* @param contact subjects BareJid. * @param contact subjects BareJid.
* @param contactsDeviceList subjects deviceList. * @param contactsDeviceList subjects deviceList.
* @return copy of subjects deviceList with stale devices marked as inactive. * @return copy of subjects deviceList with stale devices marked as inactive.
* @throws IOException
*/ */
private OmemoCachedDeviceList removeStaleDevicesFromDeviceList(OmemoDevice userDevice, private OmemoCachedDeviceList removeStaleDevicesFromDeviceList(OmemoDevice userDevice,
BareJid contact, BareJid contact,
OmemoCachedDeviceList contactsDeviceList, OmemoCachedDeviceList contactsDeviceList,
int maxAgeHours) { int maxAgeHours) throws IOException {
OmemoCachedDeviceList deviceList = new OmemoCachedDeviceList(contactsDeviceList); // Don't work on original list. OmemoCachedDeviceList deviceList = new OmemoCachedDeviceList(contactsDeviceList); // Don't work on original list.
// Iterate through original list, but modify copy instead // Iterate through original list, but modify copy instead
@ -1024,9 +1040,10 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
* @param managerGuard authenticated OmemoManager. * @param managerGuard authenticated OmemoManager.
* @param mamQuery Mam archive query * @param mamQuery Mam archive query
* @return list of {@link MessageOrOmemoMessage}s. * @return list of {@link MessageOrOmemoMessage}s.
* @throws IOException
*/ */
List<MessageOrOmemoMessage> decryptMamQueryResult(OmemoManager.LoggedInOmemoManager managerGuard, List<MessageOrOmemoMessage> decryptMamQueryResult(OmemoManager.LoggedInOmemoManager managerGuard,
MamManager.MamQuery mamQuery) { MamManager.MamQuery mamQuery) throws IOException {
List<MessageOrOmemoMessage> result = new ArrayList<>(); List<MessageOrOmemoMessage> result = new ArrayList<>();
for (Message message : mamQuery.getMessages()) { for (Message message : mamQuery.getMessages()) {
if (OmemoManager.stanzaContainsOmemoElement(message)) { if (OmemoManager.stanzaContainsOmemoElement(message)) {
@ -1055,7 +1072,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
public void onOmemoCarbonCopyReceived(CarbonExtension.Direction direction, public void onOmemoCarbonCopyReceived(CarbonExtension.Direction direction,
Message carbonCopy, Message carbonCopy,
Message wrappingMessage, Message wrappingMessage,
OmemoManager.LoggedInOmemoManager managerGuard) { OmemoManager.LoggedInOmemoManager managerGuard) throws IOException {
OmemoManager manager = managerGuard.get(); OmemoManager manager = managerGuard.get();
// Avoid the ratchet being manipulated and the bundle being published multiple times simultaneously // Avoid the ratchet being manipulated and the bundle being published multiple times simultaneously
synchronized (manager.LOCK) { synchronized (manager.LOCK) {
@ -1110,7 +1127,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
} }
@Override @Override
public void onOmemoMessageStanzaReceived(Stanza stanza, OmemoManager.LoggedInOmemoManager managerGuard) { public void onOmemoMessageStanzaReceived(Stanza stanza, OmemoManager.LoggedInOmemoManager managerGuard) throws IOException {
OmemoManager manager = managerGuard.get(); OmemoManager manager = managerGuard.get();
// Avoid the ratchet being manipulated and the bundle being published multiple times simultaneously // Avoid the ratchet being manipulated and the bundle being published multiple times simultaneously
synchronized (manager.LOCK) { synchronized (manager.LOCK) {
@ -1197,8 +1214,9 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
* @param stanza stanza * @param stanza stanza
* @param managerGuard authenticated OmemoManager * @param managerGuard authenticated OmemoManager
* @return decrypted OmemoMessage or null * @return decrypted OmemoMessage or null
* @throws IOException
*/ */
OmemoMessage.Received decryptStanza(Stanza stanza, OmemoManager.LoggedInOmemoManager managerGuard) { OmemoMessage.Received decryptStanza(Stanza stanza, OmemoManager.LoggedInOmemoManager managerGuard) throws IOException {
OmemoManager manager = managerGuard.get(); OmemoManager manager = managerGuard.get();
// Avoid the ratchet being manipulated and the bundle being published multiple times simultaneously // Avoid the ratchet being manipulated and the bundle being published multiple times simultaneously
synchronized (manager.LOCK) { synchronized (manager.LOCK) {
@ -1275,9 +1293,10 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
* *
* @param managerGuard authenticated OmemoManager. * @param managerGuard authenticated OmemoManager.
* @param brokenDevice device which session broke. * @param brokenDevice device which session broke.
* @throws IOException
*/ */
private void repairBrokenSessionWithPreKeyMessage(OmemoManager.LoggedInOmemoManager managerGuard, private void repairBrokenSessionWithPreKeyMessage(OmemoManager.LoggedInOmemoManager managerGuard,
OmemoDevice brokenDevice) { OmemoDevice brokenDevice) throws IOException {
LOGGER.log(Level.WARNING, "Attempt to repair the session by sending a fresh preKey message to " LOGGER.log(Level.WARNING, "Attempt to repair the session by sending a fresh preKey message to "
+ brokenDevice); + brokenDevice);
@ -1307,11 +1326,12 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
* @throws SmackException.NotConnectedException * @throws SmackException.NotConnectedException
* @throws CryptoFailedException if encryption fails (should not happen though, but who knows...) * @throws CryptoFailedException if encryption fails (should not happen though, but who knows...)
* @throws CannotEstablishOmemoSessionException if we cannot establish a session with contactsDevice. * @throws CannotEstablishOmemoSessionException if we cannot establish a session with contactsDevice.
* @throws IOException
*/ */
private void sendRatchetUpdate(OmemoManager.LoggedInOmemoManager managerGuard, OmemoDevice contactsDevice) private void sendRatchetUpdate(OmemoManager.LoggedInOmemoManager managerGuard, OmemoDevice contactsDevice)
throws CorruptedOmemoKeyException, InterruptedException, SmackException.NoResponseException, throws CorruptedOmemoKeyException, InterruptedException, SmackException.NoResponseException,
NoSuchAlgorithmException, SmackException.NotConnectedException, CryptoFailedException, NoSuchAlgorithmException, SmackException.NotConnectedException, CryptoFailedException,
CannotEstablishOmemoSessionException { CannotEstablishOmemoSessionException, IOException {
OmemoManager manager = managerGuard.get(); OmemoManager manager = managerGuard.get();
OmemoElement ratchetUpdate = createRatchetUpdateElement(managerGuard, contactsDevice); OmemoElement ratchetUpdate = createRatchetUpdateElement(managerGuard, contactsDevice);
@ -1350,10 +1370,11 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
* @throws XMPPException.XMPPErrorException * @throws XMPPException.XMPPErrorException
* @throws SmackException.NotConnectedException * @throws SmackException.NotConnectedException
* @throws SmackException.NoResponseException * @throws SmackException.NoResponseException
* @throws IOException
*/ */
public void purgeDeviceList(OmemoManager.LoggedInOmemoManager managerGuard) public void purgeDeviceList(OmemoManager.LoggedInOmemoManager managerGuard)
throws InterruptedException, XMPPException.XMPPErrorException, SmackException.NotConnectedException, throws InterruptedException, XMPPException.XMPPErrorException, SmackException.NotConnectedException,
SmackException.NoResponseException { SmackException.NoResponseException, IOException {
OmemoManager omemoManager = managerGuard.get(); OmemoManager omemoManager = managerGuard.get();
OmemoDevice userDevice = omemoManager.getOwnDevice(); OmemoDevice userDevice = omemoManager.getOwnDevice();

View File

@ -18,6 +18,7 @@ package org.jivesoftware.smackx.omemo;
import static org.jivesoftware.smackx.omemo.util.OmemoConstants.PRE_KEY_COUNT_PER_BUNDLE; import static org.jivesoftware.smackx.omemo.util.OmemoConstants.PRE_KEY_COUNT_PER_BUNDLE;
import java.io.IOException;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -78,8 +79,9 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
* @param userDevice our current device. * @param userDevice our current device.
* @param id deviceId to check for. * @param id deviceId to check for.
* @return true if list did not contain our id, else false * @return true if list did not contain our id, else false
* @throws IOException
*/ */
boolean isAvailableDeviceId(OmemoDevice userDevice, int id) { boolean isAvailableDeviceId(OmemoDevice userDevice, int id) throws IOException {
LOGGER.log(Level.INFO, "Check if id " + id + " is available..."); LOGGER.log(Level.INFO, "Check if id " + id + " is available...");
// Lookup local cached device list // Lookup local cached device list
@ -101,8 +103,9 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
* @param userDevice our OmemoDevice. * @param userDevice our OmemoDevice.
* @param contact Contact we received the list from. * @param contact Contact we received the list from.
* @param list List we received. * @param list List we received.
* @throws IOException
*/ */
OmemoCachedDeviceList mergeCachedDeviceList(OmemoDevice userDevice, BareJid contact, OmemoDeviceListElement list) { OmemoCachedDeviceList mergeCachedDeviceList(OmemoDevice userDevice, BareJid contact, OmemoDeviceListElement list) throws IOException {
OmemoCachedDeviceList cached = loadCachedDeviceList(userDevice, contact); OmemoCachedDeviceList cached = loadCachedDeviceList(userDevice, contact);
if (cached == null) { if (cached == null) {
@ -131,10 +134,11 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
* *
* @param userDevice our OmemoDevice. * @param userDevice our OmemoDevice.
* @throws CorruptedOmemoKeyException when our identityKey is invalid. * @throws CorruptedOmemoKeyException when our identityKey is invalid.
* @throws IOException
* @throws IllegalStateException when our IdentityKeyPair is null. * @throws IllegalStateException when our IdentityKeyPair is null.
*/ */
void changeSignedPreKey(OmemoDevice userDevice) void changeSignedPreKey(OmemoDevice userDevice)
throws CorruptedOmemoKeyException { throws CorruptedOmemoKeyException, IOException {
T_IdKeyPair idKeyPair = loadOmemoIdentityKeyPair(userDevice); T_IdKeyPair idKeyPair = loadOmemoIdentityKeyPair(userDevice);
if (idKeyPair == null) { if (idKeyPair == null) {
@ -159,8 +163,9 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
* Remove the oldest signedPreKey until there are only MAX_NUMBER_OF_STORED_SIGNED_PREKEYS left. * Remove the oldest signedPreKey until there are only MAX_NUMBER_OF_STORED_SIGNED_PREKEYS left.
* *
* @param userDevice our OmemoDevice. * @param userDevice our OmemoDevice.
* @throws IOException
*/ */
private void removeOldSignedPreKeys(OmemoDevice userDevice) { private void removeOldSignedPreKeys(OmemoDevice userDevice) throws IOException {
if (OmemoConfiguration.getMaxNumberOfStoredSignedPreKeys() <= 0) { if (OmemoConfiguration.getMaxNumberOfStoredSignedPreKeys() <= 0) {
return; return;
} }
@ -181,9 +186,10 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
* @param userDevice our OmemoDevice. * @param userDevice our OmemoDevice.
* @return OmemoBundleElement * @return OmemoBundleElement
* @throws CorruptedOmemoKeyException when a key could not be loaded * @throws CorruptedOmemoKeyException when a key could not be loaded
* @throws IOException
*/ */
OmemoBundleElement_VAxolotl packOmemoBundle(OmemoDevice userDevice) OmemoBundleElement_VAxolotl packOmemoBundle(OmemoDevice userDevice)
throws CorruptedOmemoKeyException { throws CorruptedOmemoKeyException, IOException {
int currentSignedPreKeyId = loadCurrentOmemoSignedPreKeyId(userDevice); int currentSignedPreKeyId = loadCurrentOmemoSignedPreKeyId(userDevice);
T_SigPreKey currentSignedPreKey = loadOmemoSignedPreKeys(userDevice).get(currentSignedPreKeyId); T_SigPreKey currentSignedPreKey = loadOmemoSignedPreKeys(userDevice).get(currentSignedPreKeyId);
@ -201,9 +207,10 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
* Replenish our supply of keys. If we are missing any type of keys, generate them fresh. * Replenish our supply of keys. If we are missing any type of keys, generate them fresh.
* @param userDevice * @param userDevice
* @throws CorruptedOmemoKeyException * @throws CorruptedOmemoKeyException
* @throws IOException
*/ */
public void replenishKeys(OmemoDevice userDevice) public void replenishKeys(OmemoDevice userDevice)
throws CorruptedOmemoKeyException { throws CorruptedOmemoKeyException, IOException {
T_IdKeyPair identityKeyPair = loadOmemoIdentityKeyPair(userDevice); T_IdKeyPair identityKeyPair = loadOmemoIdentityKeyPair(userDevice);
if (identityKeyPair == null) { if (identityKeyPair == null) {
@ -244,9 +251,10 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
* @param userDevice our OmemoDevice. * @param userDevice our OmemoDevice.
* @return identityKeyPair * @return identityKeyPair
* @throws CorruptedOmemoKeyException Thrown, if the stored key is damaged (*hands up* not my fault!) * @throws CorruptedOmemoKeyException Thrown, if the stored key is damaged (*hands up* not my fault!)
* @throws IOException
*/ */
public abstract T_IdKeyPair loadOmemoIdentityKeyPair(OmemoDevice userDevice) public abstract T_IdKeyPair loadOmemoIdentityKeyPair(OmemoDevice userDevice)
throws CorruptedOmemoKeyException; throws CorruptedOmemoKeyException, IOException;
/** /**
* Store our identityKeyPair in storage. It would be a cool feature, if the key could be stored in a encrypted * Store our identityKeyPair in storage. It would be a cool feature, if the key could be stored in a encrypted
@ -254,8 +262,9 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
* *
* @param userDevice our OmemoDevice. * @param userDevice our OmemoDevice.
* @param identityKeyPair identityKeyPair * @param identityKeyPair identityKeyPair
* @throws IOException
*/ */
public abstract void storeOmemoIdentityKeyPair(OmemoDevice userDevice, T_IdKeyPair identityKeyPair); public abstract void storeOmemoIdentityKeyPair(OmemoDevice userDevice, T_IdKeyPair identityKeyPair) throws IOException;
/** /**
* Remove the identityKeyPair of a user. * Remove the identityKeyPair of a user.
@ -270,9 +279,10 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
* @param contactsDevice the device of which we want to load the identityKey. * @param contactsDevice the device of which we want to load the identityKey.
* @return identityKey * @return identityKey
* @throws CorruptedOmemoKeyException when the key in question is corrupted and cant be deserialized. * @throws CorruptedOmemoKeyException when the key in question is corrupted and cant be deserialized.
* @throws IOException
*/ */
public abstract T_IdKey loadOmemoIdentityKey(OmemoDevice userDevice, OmemoDevice contactsDevice) public abstract T_IdKey loadOmemoIdentityKey(OmemoDevice userDevice, OmemoDevice contactsDevice)
throws CorruptedOmemoKeyException; throws CorruptedOmemoKeyException, IOException;
/** /**
* Store the public identityKey of the device. * Store the public identityKey of the device.
@ -280,8 +290,9 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
* @param userDevice our OmemoDevice. * @param userDevice our OmemoDevice.
* @param contactsDevice device. * @param contactsDevice device.
* @param contactsKey identityKey belonging to the contactsDevice. * @param contactsKey identityKey belonging to the contactsDevice.
* @throws IOException
*/ */
public abstract void storeOmemoIdentityKey(OmemoDevice userDevice, OmemoDevice contactsDevice, T_IdKey contactsKey); public abstract void storeOmemoIdentityKey(OmemoDevice userDevice, OmemoDevice contactsDevice, T_IdKey contactsKey) throws IOException;
/** /**
* Removes the identityKey of a device. * Removes the identityKey of a device.
@ -298,8 +309,9 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
* @param userDevice our omemoDevice. * @param userDevice our omemoDevice.
* @param contactsDevice device of which we want to set the message counter. * @param contactsDevice device of which we want to set the message counter.
* @param counter counter value. * @param counter counter value.
* @throws IOException
*/ */
public abstract void storeOmemoMessageCounter(OmemoDevice userDevice, OmemoDevice contactsDevice, int counter); public abstract void storeOmemoMessageCounter(OmemoDevice userDevice, OmemoDevice contactsDevice, int counter) throws IOException;
/** /**
* Return the current value of the message counter. * Return the current value of the message counter.
@ -309,8 +321,9 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
* @param userDevice our omemoDevice * @param userDevice our omemoDevice
* @param contactsDevice device of which we want to get the message counter. * @param contactsDevice device of which we want to get the message counter.
* @return counter value. * @return counter value.
* @throws IOException
*/ */
public abstract int loadOmemoMessageCounter(OmemoDevice userDevice, OmemoDevice contactsDevice); public abstract int loadOmemoMessageCounter(OmemoDevice userDevice, OmemoDevice contactsDevice) throws IOException;
/** /**
* Set the date of the last message that was received from a device. * Set the date of the last message that was received from a device.
@ -318,8 +331,9 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
* @param userDevice omemoManager of our device. * @param userDevice omemoManager of our device.
* @param contactsDevice device in question * @param contactsDevice device in question
* @param date date of the last received message * @param date date of the last received message
* @throws IOException
*/ */
public abstract void setDateOfLastReceivedMessage(OmemoDevice userDevice, OmemoDevice contactsDevice, Date date); public abstract void setDateOfLastReceivedMessage(OmemoDevice userDevice, OmemoDevice contactsDevice, Date date) throws IOException;
/** /**
* Return the date of the last message that was received from device 'from'. * Return the date of the last message that was received from device 'from'.
@ -327,8 +341,9 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
* @param userDevice our OmemoDevice. * @param userDevice our OmemoDevice.
* @param contactsDevice device in question * @param contactsDevice device in question
* @return date if existent, null * @return date if existent, null
* @throws IOException
*/ */
public abstract Date getDateOfLastReceivedMessage(OmemoDevice userDevice, OmemoDevice contactsDevice); public abstract Date getDateOfLastReceivedMessage(OmemoDevice userDevice, OmemoDevice contactsDevice) throws IOException;
/** /**
* Set the date of the last time the deviceId was published. This method only gets called, when the deviceId * Set the date of the last time the deviceId was published. This method only gets called, when the deviceId
@ -337,8 +352,9 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
* @param userDevice our OmemoDevice * @param userDevice our OmemoDevice
* @param contactsDevice OmemoDevice in question * @param contactsDevice OmemoDevice in question
* @param date date of the last publication after not being published * @param date date of the last publication after not being published
* @throws IOException
*/ */
public abstract void setDateOfLastDeviceIdPublication(OmemoDevice userDevice, OmemoDevice contactsDevice, Date date); public abstract void setDateOfLastDeviceIdPublication(OmemoDevice userDevice, OmemoDevice contactsDevice, Date date) throws IOException;
/** /**
* Return the date of the last time the deviceId was published after previously being not published. * Return the date of the last time the deviceId was published after previously being not published.
@ -347,24 +363,27 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
* @param userDevice our OmemoDevice * @param userDevice our OmemoDevice
* @param contactsDevice OmemoDevice in question * @param contactsDevice OmemoDevice in question
* @return date of the last publication after not being published * @return date of the last publication after not being published
* @throws IOException
*/ */
public abstract Date getDateOfLastDeviceIdPublication(OmemoDevice userDevice, OmemoDevice contactsDevice); public abstract Date getDateOfLastDeviceIdPublication(OmemoDevice userDevice, OmemoDevice contactsDevice) throws IOException;
/** /**
* Set the date of the last time the signed preKey was renewed. * Set the date of the last time the signed preKey was renewed.
* *
* @param userDevice our OmemoDevice. * @param userDevice our OmemoDevice.
* @param date date * @param date date
* @throws IOException
*/ */
public abstract void setDateOfLastSignedPreKeyRenewal(OmemoDevice userDevice, Date date); public abstract void setDateOfLastSignedPreKeyRenewal(OmemoDevice userDevice, Date date) throws IOException;
/** /**
* Get the date of the last time the signed preKey was renewed. * Get the date of the last time the signed preKey was renewed.
* *
* @param userDevice our OmemoDevice. * @param userDevice our OmemoDevice.
* @return date if existent, otherwise null * @return date if existent, otherwise null
* @throws IOException
*/ */
public abstract Date getDateOfLastSignedPreKeyRenewal(OmemoDevice userDevice); public abstract Date getDateOfLastSignedPreKeyRenewal(OmemoDevice userDevice) throws IOException;
/** /**
* Generate 'count' new PreKeys beginning with id 'startId'. * Generate 'count' new PreKeys beginning with id 'startId'.
@ -384,8 +403,9 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
* @param userDevice our OmemoDevice. * @param userDevice our OmemoDevice.
* @param preKeyId id of the key to be loaded * @param preKeyId id of the key to be loaded
* @return loaded preKey * @return loaded preKey
* @throws IOException
*/ */
public abstract T_PreKey loadOmemoPreKey(OmemoDevice userDevice, int preKeyId); public abstract T_PreKey loadOmemoPreKey(OmemoDevice userDevice, int preKeyId) throws IOException;
/** /**
* Store a PreKey in storage. * Store a PreKey in storage.
@ -393,16 +413,18 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
* @param userDevice our OmemoDevice. * @param userDevice our OmemoDevice.
* @param preKeyId id of the key * @param preKeyId id of the key
* @param preKey key * @param preKey key
* @throws IOException
*/ */
public abstract void storeOmemoPreKey(OmemoDevice userDevice, int preKeyId, T_PreKey preKey); public abstract void storeOmemoPreKey(OmemoDevice userDevice, int preKeyId, T_PreKey preKey) throws IOException;
/** /**
* Store a whole bunch of preKeys. * Store a whole bunch of preKeys.
* *
* @param userDevice our OmemoDevice. * @param userDevice our OmemoDevice.
* @param preKeyHashMap HashMap of preKeys * @param preKeyHashMap HashMap of preKeys
* @throws IOException
*/ */
public void storeOmemoPreKeys(OmemoDevice userDevice, TreeMap<Integer, T_PreKey> preKeyHashMap) { public void storeOmemoPreKeys(OmemoDevice userDevice, TreeMap<Integer, T_PreKey> preKeyHashMap) throws IOException {
for (Map.Entry<Integer, T_PreKey> entry : preKeyHashMap.entrySet()) { for (Map.Entry<Integer, T_PreKey> entry : preKeyHashMap.entrySet()) {
storeOmemoPreKey(userDevice, entry.getKey(), entry.getValue()); storeOmemoPreKey(userDevice, entry.getKey(), entry.getValue());
} }
@ -422,8 +444,9 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
* *
* @param userDevice our OmemoDevice. * @param userDevice our OmemoDevice.
* @return Map containing our preKeys * @return Map containing our preKeys
* @throws IOException
*/ */
public abstract TreeMap<Integer, T_PreKey> loadOmemoPreKeys(OmemoDevice userDevice); public abstract TreeMap<Integer, T_PreKey> loadOmemoPreKeys(OmemoDevice userDevice) throws IOException;
/** /**
* Return the signedPreKey with the id 'singedPreKeyId'. * Return the signedPreKey with the id 'singedPreKeyId'.
@ -431,10 +454,11 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
* @param userDevice our OmemoDevice. * @param userDevice our OmemoDevice.
* @param signedPreKeyId id of the key * @param signedPreKeyId id of the key
* @return key * @return key
* @throws IOException
*/ */
public abstract T_SigPreKey loadOmemoSignedPreKey(OmemoDevice userDevice, int signedPreKeyId); public abstract T_SigPreKey loadOmemoSignedPreKey(OmemoDevice userDevice, int signedPreKeyId) throws IOException;
public int loadCurrentOmemoSignedPreKeyId(OmemoDevice userDevice) { public int loadCurrentOmemoSignedPreKeyId(OmemoDevice userDevice) throws IOException {
return loadOmemoSignedPreKeys(userDevice).lastKey(); return loadOmemoSignedPreKeys(userDevice).lastKey();
} }
@ -443,8 +467,9 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
* *
* @param userDevice our OmemoDevice. * @param userDevice our OmemoDevice.
* @return HashMap of our singedPreKeys * @return HashMap of our singedPreKeys
* @throws IOException
*/ */
public abstract TreeMap<Integer, T_SigPreKey> loadOmemoSignedPreKeys(OmemoDevice userDevice); public abstract TreeMap<Integer, T_SigPreKey> loadOmemoSignedPreKeys(OmemoDevice userDevice) throws IOException;
/** /**
* Generate a new signed preKey. * Generate a new signed preKey.
@ -465,8 +490,9 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
* @param userDevice our OmemoDevice. * @param userDevice our OmemoDevice.
* @param signedPreKeyId id of the signedPreKey * @param signedPreKeyId id of the signedPreKey
* @param signedPreKey the key itself * @param signedPreKey the key itself
* @throws IOException
*/ */
public abstract void storeOmemoSignedPreKey(OmemoDevice userDevice, int signedPreKeyId, T_SigPreKey signedPreKey); public abstract void storeOmemoSignedPreKey(OmemoDevice userDevice, int signedPreKeyId, T_SigPreKey signedPreKey) throws IOException;
/** /**
* Remove a signedPreKey from storage. * Remove a signedPreKey from storage.
@ -482,8 +508,9 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
* @param userDevice our OmemoDevice. * @param userDevice our OmemoDevice.
* @param contactsDevice device whose session we want to load * @param contactsDevice device whose session we want to load
* @return crypto related session * @return crypto related session
* @throws IOException
*/ */
public abstract T_Sess loadRawSession(OmemoDevice userDevice, OmemoDevice contactsDevice); public abstract T_Sess loadRawSession(OmemoDevice userDevice, OmemoDevice contactsDevice) throws IOException;
/** /**
* Load all crypto-lib specific session objects of contact 'contact'. * Load all crypto-lib specific session objects of contact 'contact'.
@ -491,8 +518,9 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
* @param userDevice our OmemoDevice. * @param userDevice our OmemoDevice.
* @param contact BareJid of the contact we want to get all sessions from * @param contact BareJid of the contact we want to get all sessions from
* @return TreeMap of deviceId and sessions of the contact * @return TreeMap of deviceId and sessions of the contact
* @throws IOException
*/ */
public abstract HashMap<Integer, T_Sess> loadAllRawSessionsOf(OmemoDevice userDevice, BareJid contact); public abstract HashMap<Integer, T_Sess> loadAllRawSessionsOf(OmemoDevice userDevice, BareJid contact) throws IOException;
/** /**
* Store a crypto-lib specific session to storage. * Store a crypto-lib specific session to storage.
@ -500,8 +528,9 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
* @param userDevice our OmemoDevice. * @param userDevice our OmemoDevice.
* @param contactsDevice OmemoDevice whose session we want to store * @param contactsDevice OmemoDevice whose session we want to store
* @param session session * @param session session
* @throws IOException
*/ */
public abstract void storeRawSession(OmemoDevice userDevice, OmemoDevice contactsDevice, T_Sess session); public abstract void storeRawSession(OmemoDevice userDevice, OmemoDevice contactsDevice, T_Sess session) throws IOException;
/** /**
* Remove a crypto-lib specific session from storage. * Remove a crypto-lib specific session from storage.
@ -535,15 +564,17 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
* @param userDevice our OmemoDevice. * @param userDevice our OmemoDevice.
* @param contact contact we want to get the deviceList of * @param contact contact we want to get the deviceList of
* @return CachedDeviceList of the contact * @return CachedDeviceList of the contact
* @throws IOException
*/ */
public abstract OmemoCachedDeviceList loadCachedDeviceList(OmemoDevice userDevice, BareJid contact); public abstract OmemoCachedDeviceList loadCachedDeviceList(OmemoDevice userDevice, BareJid contact) throws IOException;
/** /**
* Load a list of deviceIds from our own devices. * Load a list of deviceIds from our own devices.
* @param userDevice * @param userDevice
* @return * @return
* @throws IOException
*/ */
public OmemoCachedDeviceList loadCachedDeviceList(OmemoDevice userDevice) { public OmemoCachedDeviceList loadCachedDeviceList(OmemoDevice userDevice) throws IOException {
return loadCachedDeviceList(userDevice, userDevice.getJid()); return loadCachedDeviceList(userDevice, userDevice.getJid());
} }
@ -554,10 +585,11 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
* @param userDevice our OmemoDevice. * @param userDevice our OmemoDevice.
* @param contact Contact * @param contact Contact
* @param contactsDeviceList list of the contacts devices' ids. * @param contactsDeviceList list of the contacts devices' ids.
* @throws IOException
*/ */
public abstract void storeCachedDeviceList(OmemoDevice userDevice, public abstract void storeCachedDeviceList(OmemoDevice userDevice,
BareJid contact, BareJid contact,
OmemoCachedDeviceList contactsDeviceList); OmemoCachedDeviceList contactsDeviceList) throws IOException;
/** /**
* Delete this device's IdentityKey, PreKeys, SignedPreKeys and Sessions. * Delete this device's IdentityKey, PreKeys, SignedPreKeys and Sessions.
@ -580,9 +612,10 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
* @return fingerprint of our identityKeyPair * @return fingerprint of our identityKeyPair
* *
* @throws CorruptedOmemoKeyException if the identityKey of userDevice is corrupted. * @throws CorruptedOmemoKeyException if the identityKey of userDevice is corrupted.
* @throws IOException
*/ */
public OmemoFingerprint getFingerprint(OmemoDevice userDevice) public OmemoFingerprint getFingerprint(OmemoDevice userDevice)
throws CorruptedOmemoKeyException { throws CorruptedOmemoKeyException, IOException {
T_IdKeyPair keyPair = loadOmemoIdentityKeyPair(userDevice); T_IdKeyPair keyPair = loadOmemoIdentityKeyPair(userDevice);
if (keyPair == null) { if (keyPair == null) {
@ -600,9 +633,10 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
* @return fingerprint of the userDevices IdentityKey. * @return fingerprint of the userDevices IdentityKey.
* @throws CorruptedOmemoKeyException if the IdentityKey is corrupted. * @throws CorruptedOmemoKeyException if the IdentityKey is corrupted.
* @throws NoIdentityKeyException if no IdentityKey for contactsDevice has been found locally. * @throws NoIdentityKeyException if no IdentityKey for contactsDevice has been found locally.
* @throws IOException
*/ */
public OmemoFingerprint getFingerprint(OmemoDevice userDevice, OmemoDevice contactsDevice) public OmemoFingerprint getFingerprint(OmemoDevice userDevice, OmemoDevice contactsDevice)
throws CorruptedOmemoKeyException, NoIdentityKeyException { throws CorruptedOmemoKeyException, NoIdentityKeyException, IOException {
T_IdKey identityKey = loadOmemoIdentityKey(userDevice, contactsDevice); T_IdKey identityKey = loadOmemoIdentityKey(userDevice, contactsDevice);
if (identityKey == null) { if (identityKey == null) {
@ -625,10 +659,11 @@ public abstract class OmemoStore<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
* @throws SmackException.NotConnectedException * @throws SmackException.NotConnectedException
* @throws InterruptedException * @throws InterruptedException
* @throws SmackException.NoResponseException * @throws SmackException.NoResponseException
* @throws IOException
*/ */
public OmemoFingerprint getFingerprintAndMaybeBuildSession(OmemoManager.LoggedInOmemoManager managerGuard, OmemoDevice contactsDevice) public OmemoFingerprint getFingerprintAndMaybeBuildSession(OmemoManager.LoggedInOmemoManager managerGuard, OmemoDevice contactsDevice)
throws CannotEstablishOmemoSessionException, CorruptedOmemoKeyException, throws CannotEstablishOmemoSessionException, CorruptedOmemoKeyException,
SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException { SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException, IOException {
OmemoManager omemoManager = managerGuard.get(); OmemoManager omemoManager = managerGuard.get();
// Load identityKey // Load identityKey

View File

@ -16,6 +16,8 @@
*/ */
package org.jivesoftware.smackx.omemo.internal.listener; package org.jivesoftware.smackx.omemo.internal.listener;
import java.io.IOException;
import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smackx.carbons.packet.CarbonExtension; import org.jivesoftware.smackx.carbons.packet.CarbonExtension;
@ -26,5 +28,6 @@ import org.jivesoftware.smackx.omemo.OmemoManager;
*/ */
public interface OmemoCarbonCopyStanzaReceivedListener { public interface OmemoCarbonCopyStanzaReceivedListener {
void onOmemoCarbonCopyReceived(CarbonExtension.Direction direction, Message carbonCopy, Message wrappingMessage, OmemoManager.LoggedInOmemoManager omemoManager); void onOmemoCarbonCopyReceived(CarbonExtension.Direction direction, Message carbonCopy, Message wrappingMessage,
OmemoManager.LoggedInOmemoManager omemoManager) throws IOException;
} }

View File

@ -16,11 +16,13 @@
*/ */
package org.jivesoftware.smackx.omemo.internal.listener; package org.jivesoftware.smackx.omemo.internal.listener;
import java.io.IOException;
import org.jivesoftware.smack.packet.Stanza; import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smackx.omemo.OmemoManager; import org.jivesoftware.smackx.omemo.OmemoManager;
public interface OmemoMessageStanzaReceivedListener { public interface OmemoMessageStanzaReceivedListener {
void onOmemoMessageStanzaReceived(Stanza stanza, OmemoManager.LoggedInOmemoManager omemoManager); void onOmemoMessageStanzaReceived(Stanza stanza, OmemoManager.LoggedInOmemoManager omemoManager) throws IOException;
} }

View File

@ -20,6 +20,7 @@ import static org.jivesoftware.smackx.omemo.util.OmemoConstants.Crypto.CIPHERMOD
import static org.jivesoftware.smackx.omemo.util.OmemoConstants.Crypto.KEYLENGTH; import static org.jivesoftware.smackx.omemo.util.OmemoConstants.Crypto.KEYLENGTH;
import static org.jivesoftware.smackx.omemo.util.OmemoConstants.Crypto.KEYTYPE; import static org.jivesoftware.smackx.omemo.util.OmemoConstants.Crypto.KEYTYPE;
import java.io.IOException;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException; import java.security.InvalidAlgorithmParameterException;
@ -219,10 +220,11 @@ public class OmemoMessageBuilder<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey, T_
* @throws CorruptedOmemoKeyException if the identityKey of that device is corrupted. * @throws CorruptedOmemoKeyException if the identityKey of that device is corrupted.
* @throws UndecidedOmemoIdentityException if the user hasn't yet decided whether to trust that device or not. * @throws UndecidedOmemoIdentityException if the user hasn't yet decided whether to trust that device or not.
* @throws UntrustedOmemoIdentityException if the user has decided not to trust that device. * @throws UntrustedOmemoIdentityException if the user has decided not to trust that device.
* @throws IOException
*/ */
public void addRecipient(OmemoDevice contactsDevice) public void addRecipient(OmemoDevice contactsDevice)
throws NoIdentityKeyException, CorruptedOmemoKeyException, UndecidedOmemoIdentityException, throws NoIdentityKeyException, CorruptedOmemoKeyException, UndecidedOmemoIdentityException,
UntrustedOmemoIdentityException { UntrustedOmemoIdentityException, IOException {
OmemoFingerprint fingerprint; OmemoFingerprint fingerprint;
fingerprint = OmemoService.getInstance().getOmemoStoreBackend().getFingerprint(userDevice, contactsDevice); fingerprint = OmemoService.getInstance().getOmemoStoreBackend().getFingerprint(userDevice, contactsDevice);

View File

@ -302,20 +302,20 @@ public abstract class OmemoStoreTest<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey
} }
@Test @Test
public void loadAllRawSessionsReturnsEmptyMapTest() { public void loadAllRawSessionsReturnsEmptyMapTest() throws IOException {
HashMap<Integer, T_Sess> sessions = store.loadAllRawSessionsOf(alice, bob.getJid()); HashMap<Integer, T_Sess> sessions = store.loadAllRawSessionsOf(alice, bob.getJid());
assertNotNull(sessions); assertNotNull(sessions);
assertEquals(0, sessions.size()); assertEquals(0, sessions.size());
} }
@Test @Test
public void loadNonExistentRawSessionReturnsNullTest() { public void loadNonExistentRawSessionReturnsNullTest() throws IOException {
T_Sess session = store.loadRawSession(alice, bob); T_Sess session = store.loadRawSession(alice, bob);
assertNull(session); assertNull(session);
} }
@Test @Test
public void loadStoreMessageCounterTest() { public void loadStoreMessageCounterTest() throws IOException {
assertEquals(0, store.loadOmemoMessageCounter(alice, bob)); assertEquals(0, store.loadOmemoMessageCounter(alice, bob));
store.storeOmemoMessageCounter(alice, bob, 20); store.storeOmemoMessageCounter(alice, bob, 20);
assertEquals(20, store.loadOmemoMessageCounter(alice, bob)); assertEquals(20, store.loadOmemoMessageCounter(alice, bob));