1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2025-09-11 18:19:38 +02:00

Merge master 4.2.1

This commit is contained in:
vanitasvitae 2017-08-14 22:15:23 +02:00
commit 9ff0333032
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
42 changed files with 357 additions and 256 deletions

View file

@ -19,7 +19,6 @@ package org.jivesoftware.smackx.omemo;
import static org.jivesoftware.smackx.omemo.util.OmemoConstants.BODY_OMEMO_HINT;
import static org.jivesoftware.smackx.omemo.util.OmemoConstants.OMEMO;
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 java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
@ -32,8 +31,8 @@ import java.util.WeakHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jivesoftware.smack.AbstractConnectionListener;
import org.jivesoftware.smack.AbstractXMPPConnection;
import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.Manager;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPConnection;
@ -41,7 +40,7 @@ import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smack.util.Async;
import org.jivesoftware.smack.util.stringencoder.Base64;
import org.jivesoftware.smackx.carbons.CarbonManager;
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
@ -113,8 +112,29 @@ public final class OmemoManager extends Manager implements JingleEncryptionMetho
*/
private OmemoManager(XMPPConnection connection, int deviceId) {
super(connection);
setConnectionListener();
this.deviceId = deviceId;
connection.addConnectionListener(new AbstractConnectionListener() {
@Override
public void authenticated(XMPPConnection connection, boolean resumed) {
if (resumed) {
return;
}
Async.go(new Runnable() {
@Override
public void run() {
try {
initialize();
} catch (InterruptedException | CorruptedOmemoKeyException | PubSubException.NotALeafNodeException | SmackException.NotLoggedInException | SmackException.NoResponseException | SmackException.NotConnectedException | XMPPException.XMPPErrorException e) {
LOGGER.log(Level.SEVERE, "connectionListener.authenticated() failed to initialize OmemoManager: "
+ e.getMessage());
}
}
});
}
});
service = OmemoService.getInstance();
ServiceDiscoveryManager.getInstanceFor(connection).addFeature(OmemoConstants.OMEMO_NAMESPACE_V_AXOLOTL);
}
@ -167,13 +187,13 @@ public final class OmemoManager extends Manager implements JingleEncryptionMetho
}
}
int defaulDeviceId = OmemoService.getInstance().getOmemoStoreBackend().getDefaultDeviceId(user);
if (defaulDeviceId < 1) {
defaulDeviceId = randomDeviceId();
OmemoService.getInstance().getOmemoStoreBackend().setDefaultDeviceId(user, defaulDeviceId);
int defaultDeviceId = OmemoService.getInstance().getOmemoStoreBackend().getDefaultDeviceId(user);
if (defaultDeviceId < 1) {
defaultDeviceId = randomDeviceId();
OmemoService.getInstance().getOmemoStoreBackend().setDefaultDeviceId(user, defaultDeviceId);
}
return getInstanceFor(connection, defaulDeviceId);
return getInstanceFor(connection, defaultDeviceId);
}
/**
@ -475,24 +495,6 @@ public final class OmemoManager extends Manager implements JingleEncryptionMetho
.getActiveDevices().isEmpty();
}
/**
* Returns true, if the device resource has announced OMEMO support.
* Throws an IllegalArgumentException if the provided FullJid does not have a resource part.
*
* @param fullJid jid of a resource
* @return true if resource supports OMEMO
* @throws XMPPException.XMPPErrorException if
* @throws SmackException.NotConnectedException something
* @throws InterruptedException goes
* @throws SmackException.NoResponseException wrong
*/
public boolean resourceSupportsOmemo(FullJid fullJid) throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException {
if (fullJid.hasNoResource()) {
throw new IllegalArgumentException("Jid " + fullJid + " has no resource part.");
}
return ServiceDiscoveryManager.getInstanceFor(connection()).discoverInfo(fullJid).containsFeature(PEP_NODE_DEVICE_LIST_NOTIFY);
}
/**
* Returns true, if the MUC with the EntityBareJid multiUserChat is non-anonymous and members only (prerequisite
* for OMEMO encryption in MUC).
@ -645,54 +647,6 @@ public final class OmemoManager extends Manager implements JingleEncryptionMetho
}
}
private void setConnectionListener() {
connection().addConnectionListener(new ConnectionListener() {
@Override
public void connected(XMPPConnection connection) {
LOGGER.log(Level.INFO, "connected");
}
@Override
public void authenticated(XMPPConnection connection, boolean resumed) {
LOGGER.log(Level.INFO, "authenticated. Resumed: " + resumed);
if (resumed) {
return;
}
try {
initialize();
} catch (InterruptedException | CorruptedOmemoKeyException | PubSubException.NotALeafNodeException | SmackException.NotLoggedInException | SmackException.NoResponseException | SmackException.NotConnectedException | XMPPException.XMPPErrorException e) {
LOGGER.log(Level.SEVERE, "connectionListener.authenticated() failed to initialize OmemoManager: "
+ e.getMessage());
}
}
@Override
public void connectionClosed() {
}
@Override
public void connectionClosedOnError(Exception e) {
connectionClosed();
}
@Override
public void reconnectionSuccessful() {
}
@Override
public void reconnectingIn(int seconds) {
}
@Override
public void reconnectionFailed(Exception e) {
}
});
}
public static int randomDeviceId() {
int i = new Random().nextInt(Integer.MAX_VALUE);

View file

@ -50,6 +50,7 @@ import org.jivesoftware.smack.filter.StanzaFilter;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smack.packet.XMPPError;
import org.jivesoftware.smack.util.Async;
import org.jivesoftware.smackx.carbons.CarbonCopyReceivedListener;
import org.jivesoftware.smackx.carbons.CarbonManager;
import org.jivesoftware.smackx.carbons.packet.CarbonExtension;
@ -80,8 +81,8 @@ import org.jivesoftware.smackx.omemo.util.OmemoMessageBuilder;
import org.jivesoftware.smackx.pep.PEPManager;
import org.jivesoftware.smackx.pubsub.LeafNode;
import org.jivesoftware.smackx.pubsub.PayloadItem;
import org.jivesoftware.smackx.pubsub.PubSubAssertionError;
import org.jivesoftware.smackx.pubsub.PubSubException;
import org.jivesoftware.smackx.pubsub.PubSubException.NotAPubSubNodeException;
import org.jivesoftware.smackx.pubsub.PubSubManager;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
@ -426,11 +427,11 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
* @throws XMPPException.XMPPErrorException
* @throws SmackException.NotConnectedException
* @throws SmackException.NoResponseException
* @throws PubSubAssertionError.DiscoInfoNodeAssertionError ejabberd bug: https://github.com/processone/ejabberd/issues/1717
* @throws NotAPubSubNodeException
*/
static LeafNode fetchDeviceListNode(OmemoManager omemoManager, BareJid contact)
throws InterruptedException, PubSubException.NotALeafNodeException, XMPPException.XMPPErrorException,
SmackException.NotConnectedException, SmackException.NoResponseException, PubSubAssertionError.DiscoInfoNodeAssertionError {
SmackException.NotConnectedException, SmackException.NoResponseException, NotAPubSubNodeException {
return PubSubManager.getInstance(omemoManager.getConnection(), contact).getLeafNode(PEP_NODE_DEVICE_LIST);
}
@ -445,9 +446,11 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
* @throws InterruptedException goes
* @throws SmackException.NoResponseException wrong
* @throws PubSubException.NotALeafNodeException when the device lists node is not a LeafNode
* @throws PubSubAssertionError.DiscoInfoNodeAssertionError ejabberd bug: https://github.com/processone/ejabberd/issues/1717
* @throws NotAPubSubNodeException
*/
static OmemoDeviceListElement fetchDeviceList(OmemoManager omemoManager, BareJid contact) throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException, PubSubException.NotALeafNodeException, PubSubAssertionError.DiscoInfoNodeAssertionError {
static OmemoDeviceListElement fetchDeviceList(OmemoManager omemoManager, BareJid contact)
throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException,
SmackException.NoResponseException, PubSubException.NotALeafNodeException, NotAPubSubNodeException {
return extractDeviceListFrom(fetchDeviceListNode(omemoManager, contact));
}
@ -481,9 +484,9 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
e.getMessage());
}
catch (PubSubAssertionError.DiscoInfoNodeAssertionError bug) {
catch (PubSubException.NotAPubSubNodeException e) {
LOGGER.log(Level.WARNING, "Caught a PubSubAssertionError when fetching a deviceList node. " +
"This probably means that we're dealing with an ejabberd server and the LeafNode does not exist.");
"This probably means that we're dealing with an ejabberd server and the LeafNode does not exist.", e);
return true;
}
return false;
@ -505,9 +508,8 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
LOGGER.log(Level.WARNING, "Could not fetch device list of " + contact + ": " + e, e);
return;
}
catch (PubSubAssertionError.DiscoInfoNodeAssertionError bug) {
LOGGER.log(Level.WARNING, "Caught a PubSubAssertionError when fetching a deviceList node. " +
"This probably means that the LeafNode does not exist.");
catch (NotAPubSubNodeException e) {
LOGGER.log(Level.WARNING, "Could not fetch device list of " + contact ,e);
return;
}
@ -525,9 +527,13 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
* @throws InterruptedException goes
* @throws SmackException.NoResponseException wrong
* @throws PubSubException.NotALeafNodeException when the bundles node is not a LeafNode
* @throws NotAPubSubNodeException
*/
static OmemoBundleVAxolotlElement fetchBundle(OmemoManager omemoManager, OmemoDevice contact) throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException, PubSubException.NotALeafNodeException, PubSubAssertionError.DiscoInfoNodeAssertionError {
LeafNode node = PubSubManager.getInstance(omemoManager.getConnection(), contact.getJid()).getLeafNode(PEP_NODE_BUNDLE_FROM_DEVICE_ID(contact.getDeviceId()));
static OmemoBundleVAxolotlElement fetchBundle(OmemoManager omemoManager, OmemoDevice contact)
throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException,
SmackException.NoResponseException, PubSubException.NotALeafNodeException, NotAPubSubNodeException {
LeafNode node = PubSubManager.getInstance(omemoManager.getConnection(), contact.getJid()).getLeafNode(
PEP_NODE_BUNDLE_FROM_DEVICE_ID(contact.getDeviceId()));
return extractBundleFrom(node);
}
@ -664,7 +670,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
OmemoBundleVAxolotlElement bundle;
try {
bundle = fetchBundle(omemoManager, device);
} catch (SmackException | XMPPException.XMPPErrorException | InterruptedException | PubSubAssertionError e) {
} catch (SmackException | XMPPException.XMPPErrorException | InterruptedException e) {
throw new CannotEstablishOmemoSessionException(device, e);
}
@ -1308,7 +1314,7 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
@Override
public void onCarbonCopyReceived(CarbonExtension.Direction direction, Message carbonCopy, Message wrappingMessage) {
if (filter.accept(carbonCopy)) {
OmemoDevice senderDevice = getSender(omemoManager, carbonCopy);
final OmemoDevice senderDevice = getSender(omemoManager, carbonCopy);
Message decrypted;
MultiUserChatManager mucm = MultiUserChatManager.getInstanceFor(omemoManager.getConnection());
OmemoElement omemoMessage = carbonCopy.getExtension(OmemoElement.ENCRYPTED, OMEMO_NAMESPACE_V_AXOLOTL);
@ -1364,16 +1370,22 @@ public abstract class OmemoService<T_IdKeyPair, T_IdKey, T_PreKey, T_SigPreKey,
LOGGER.log(Level.WARNING, "internal omemoMessageListener failed to decrypt incoming OMEMO carbon copy: "
+ e.getMessage());
} catch (NoRawSessionException e) {
try {
LOGGER.log(Level.INFO, "Received OMEMO carbon copy message with invalid session from " +
senderDevice + ". Send RatchetUpdateMessage.");
service.sendOmemoRatchetUpdateMessage(omemoManager, senderDevice, true);
} catch (final NoRawSessionException e) {
Async.go(new Runnable() {
@Override
public void run() {
try {
LOGGER.log(Level.INFO, "Received OMEMO carbon copy message with invalid session from " +
senderDevice + ". Send RatchetUpdateMessage.");
service.sendOmemoRatchetUpdateMessage(omemoManager, senderDevice, true);
} catch (UndecidedOmemoIdentityException | CorruptedOmemoKeyException | CannotEstablishOmemoSessionException | CryptoFailedException e1) {
LOGGER.log(Level.WARNING, "internal omemoMessageListener failed to establish a session for incoming OMEMO carbon message: "
+ e.getMessage());
}
}
});
} catch (UndecidedOmemoIdentityException | CorruptedOmemoKeyException | CannotEstablishOmemoSessionException | CryptoFailedException e1) {
LOGGER.log(Level.WARNING, "internal omemoMessageListener failed to establish a session for incoming OMEMO carbon message: "
+ e.getMessage());
}
}
}
}

View file

@ -35,20 +35,20 @@ public class UndecidedOmemoIdentityException extends Exception {
}
/**
* Return the HashSet of untrusted devices.
* Return the HashSet of undecided devices.
*
* @return untrusted devices
* @return undecided devices
*/
public HashSet<OmemoDevice> getUntrustedDevices() {
public HashSet<OmemoDevice> getUndecidedDevices() {
return this.devices;
}
/**
* Add all untrusted devices of another Exception to this Exceptions HashSet of untrusted devices.
* Add all undecided devices of another Exception to this Exceptions HashSet of undecided devices.
*
* @param other other Exception
*/
public void join(UndecidedOmemoIdentityException other) {
this.devices.addAll(other.getUntrustedDevices());
this.devices.addAll(other.getUndecidedDevices());
}
}

View file

@ -45,18 +45,18 @@ public class OmemoExceptionsTest {
OmemoDevice mallory = new OmemoDevice(JidCreate.bareFrom("mallory@server.tld"), 9876);
UndecidedOmemoIdentityException u = new UndecidedOmemoIdentityException(alice);
assertTrue(u.getUntrustedDevices().contains(alice));
assertTrue(u.getUntrustedDevices().size() == 1);
assertTrue(u.getUndecidedDevices().contains(alice));
assertTrue(u.getUndecidedDevices().size() == 1);
UndecidedOmemoIdentityException v = new UndecidedOmemoIdentityException(bob);
v.getUntrustedDevices().add(mallory);
assertTrue(v.getUntrustedDevices().size() == 2);
assertTrue(v.getUntrustedDevices().contains(bob));
assertTrue(v.getUntrustedDevices().contains(mallory));
v.getUndecidedDevices().add(mallory);
assertTrue(v.getUndecidedDevices().size() == 2);
assertTrue(v.getUndecidedDevices().contains(bob));
assertTrue(v.getUndecidedDevices().contains(mallory));
u.getUntrustedDevices().add(bob);
u.getUndecidedDevices().add(bob);
u.join(v);
assertTrue(u.getUntrustedDevices().size() == 3);
assertTrue(u.getUndecidedDevices().size() == 3);
}
@Test