diff options
author | Christian Schneppe <christian@pix-art.de> | 2019-09-06 22:01:42 +0200 |
---|---|---|
committer | Christian Schneppe <christian@pix-art.de> | 2019-09-06 22:01:42 +0200 |
commit | c7629a60933ac61d6c38c1adb4a97c7d336514c4 (patch) | |
tree | b28ce9893f3a2aa5e911ce495992c540a73729a2 /src/main/java/de | |
parent | f8a94ec52e84a4903b55b6e456e6e7aa4a77d2be (diff) |
implemented support for for jingle encrypted transports (XEP-0396)
Diffstat (limited to 'src/main/java/de')
5 files changed, 42 insertions, 11 deletions
diff --git a/src/main/java/de/pixart/messenger/Config.java b/src/main/java/de/pixart/messenger/Config.java index 134bd3dc0..96b588b32 100644 --- a/src/main/java/de/pixart/messenger/Config.java +++ b/src/main/java/de/pixart/messenger/Config.java @@ -118,7 +118,7 @@ public final class Config { public static final int ExportLogs_Minute = 0; //Time - minutes: valid values from 0 to 59 public static final boolean DISABLE_PROXY_LOOKUP = false; //useful to debug ibb - public static final boolean USE_DIRECT_JINGLE_CANDIDATES = false; + public static final boolean USE_DIRECT_JINGLE_CANDIDATES = true; public static final boolean DISABLE_HTTP_UPLOAD = false; public static final boolean EXTENDED_SM_LOGGING = false; // log stanza counts public static final boolean BACKGROUND_STANZA_LOGGING = false; //log all stanzas that were received while the app is in background diff --git a/src/main/java/de/pixart/messenger/generator/AbstractGenerator.java b/src/main/java/de/pixart/messenger/generator/AbstractGenerator.java index a69f969f5..134ed69c7 100644 --- a/src/main/java/de/pixart/messenger/generator/AbstractGenerator.java +++ b/src/main/java/de/pixart/messenger/generator/AbstractGenerator.java @@ -29,6 +29,8 @@ public abstract class AbstractGenerator { Content.Version.FT_5.getNamespace(), Namespace.JINGLE_TRANSPORTS_S5B, Namespace.JINGLE_TRANSPORTS_IBB, + Namespace.JINGLE_ENCRYPTED_TRANSPORT, + Namespace.JINGLE_ENCRYPTED_TRANSPORT_OMEMO, "http://jabber.org/protocol/muc", "jabber:x:conference", Namespace.OOB, diff --git a/src/main/java/de/pixart/messenger/utils/Namespace.java b/src/main/java/de/pixart/messenger/utils/Namespace.java index e9af9f4a4..d8bd1728e 100644 --- a/src/main/java/de/pixart/messenger/utils/Namespace.java +++ b/src/main/java/de/pixart/messenger/utils/Namespace.java @@ -30,4 +30,6 @@ public final class Namespace { public static final String PING = "urn:xmpp:ping"; public static final String PUSH = "urn:xmpp:push:0"; public static final String COMMANDS = "http://jabber.org/protocol/commands"; + public static final String JINGLE_ENCRYPTED_TRANSPORT = "urn:xmpp:jingle:jet:0"; + public static final String JINGLE_ENCRYPTED_TRANSPORT_OMEMO = "urn:xmpp:jingle:jet-omemo:0"; } diff --git a/src/main/java/de/pixart/messenger/xmpp/jingle/JingleConnection.java b/src/main/java/de/pixart/messenger/xmpp/jingle/JingleConnection.java index bdcf32b4f..f23473356 100644 --- a/src/main/java/de/pixart/messenger/xmpp/jingle/JingleConnection.java +++ b/src/main/java/de/pixart/messenger/xmpp/jingle/JingleConnection.java @@ -48,7 +48,7 @@ import rocks.xmpp.addr.Jid; public class JingleConnection implements Transferable { private final SimpleDateFormat fileDateFormat = new SimpleDateFormat("yyyyMMdd_HHmmssSSS", Locale.US); - + private static final String JET_OMEMO_CIPHER = "urn:xmpp:ciphers:aes-128-gcm-nopadding"; private static final int JINGLE_STATUS_INITIATED = 0; private static final int JINGLE_STATUS_ACCEPTED = 1; private static final int JINGLE_STATUS_FINISHED = 4; @@ -78,6 +78,7 @@ public class JingleConnection implements Transferable { private String contentName; private String contentCreator; private Transport initialTransport; + private boolean remoteSupportsOmemoJet; private int mProgress = 0; @@ -301,8 +302,10 @@ public class JingleConnection implements Transferable { this.contentName = this.mJingleConnectionManager.nextRandomId(); this.message = message; this.account = message.getConversation().getAccount(); - upgradeNamespace(); - this.initialTransport = getRemoteFeatures().contains(Namespace.JINGLE_TRANSPORTS_S5B) ? Transport.SOCKS : Transport.IBB; + final List<String> remoteFeatures = getRemoteFeatures(); + upgradeNamespace(remoteFeatures); + this.initialTransport = remoteFeatures.contains(Namespace.JINGLE_TRANSPORTS_S5B) ? Transport.SOCKS : Transport.IBB; + this.remoteSupportsOmemoJet = remoteFeatures.contains(Namespace.JINGLE_ENCRYPTED_TRANSPORT_OMEMO); this.message.setTransferable(this); this.mStatus = Transferable.STATUS_UPLOADING; this.initiator = this.account.getJid(); @@ -361,11 +364,10 @@ public class JingleConnection implements Transferable { } } - private void upgradeNamespace() { - List<String> features = getRemoteFeatures(); - if (features.contains(Content.Version.FT_5.getNamespace())) { + private void upgradeNamespace(List<String> remoteFeatures) { + if (remoteFeatures.contains(Content.Version.FT_5.getNamespace())) { this.ftVersion = Content.Version.FT_5; - } else if (features.contains(Content.Version.FT_4.getNamespace())) { + } else if (remoteFeatures.contains(Content.Version.FT_4.getNamespace())) { this.ftVersion = Content.Version.FT_4; } } @@ -434,6 +436,13 @@ public class JingleConnection implements Transferable { this.fileOffer = content.getFileOffer(this.ftVersion); if (fileOffer != null) { Element encrypted = fileOffer.findChild("encrypted", AxolotlService.PEP_PREFIX); + if (encrypted == null) { + final Element security = content.findChild("security", Namespace.JINGLE_ENCRYPTED_TRANSPORT); + if (security != null && AxolotlService.PEP_PREFIX.equals(security.getAttribute("type"))) { + Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": received jingle file offer with JET"); + encrypted = security.findChild("encrypted", AxolotlService.PEP_PREFIX); + } + } if (encrypted != null) { this.mXmppAxolotlMessage = XmppAxolotlMessage.fromElement(encrypted, packet.getFrom().asBareJid()); } @@ -529,7 +538,18 @@ public class JingleConnection implements Transferable { this.file.setKey(mXmppAxolotlMessage.getInnerKey()); this.file.setIv(mXmppAxolotlMessage.getIV()); this.file.setExpectedSize(file.getSize() + 16); - content.setFileOffer(this.file, false, this.ftVersion).addChild(mXmppAxolotlMessage.toElement()); + final Element file = content.setFileOffer(this.file, false, this.ftVersion); + if (remoteSupportsOmemoJet) { + Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": remote announced support for JET"); + final Element security = new Element("security", Namespace.JINGLE_ENCRYPTED_TRANSPORT); + security.setAttribute("name", this.contentName); + security.setAttribute("cipher", JET_OMEMO_CIPHER); + security.setAttribute("type", AxolotlService.PEP_PREFIX); + security.addChild(mXmppAxolotlMessage.toElement()); + content.addChild(security); + } else { + file.addChild(mXmppAxolotlMessage.toElement()); + } } else { this.file.setExpectedSize(file.getSize()); content.setFileOffer(this.file, false, this.ftVersion); @@ -763,6 +783,8 @@ public class JingleConnection implements Transferable { this.sendFallbackToIbb(); } } else { + final JingleCandidate candidate = connection.getCandidate(); + Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": elected candidate " + candidate.getHost() + ":" + candidate.getPort()); this.mJingleStatus = JINGLE_STATUS_TRANSMITTING; if (connection.needsActivation()) { if (connection.getCandidate().isOurs()) { diff --git a/src/main/java/de/pixart/messenger/xmpp/jingle/JingleSocks5Transport.java b/src/main/java/de/pixart/messenger/xmpp/jingle/JingleSocks5Transport.java index 027395a5a..2bbf7c981 100644 --- a/src/main/java/de/pixart/messenger/xmpp/jingle/JingleSocks5Transport.java +++ b/src/main/java/de/pixart/messenger/xmpp/jingle/JingleSocks5Transport.java @@ -16,6 +16,7 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import de.pixart.messenger.Config; +import de.pixart.messenger.entities.Account; import de.pixart.messenger.entities.DownloadableFile; import de.pixart.messenger.persistance.FileBackend; import de.pixart.messenger.services.AbstractConnectionManager; @@ -135,11 +136,14 @@ public class JingleSocks5Transport extends JingleTransport { outputStream.write(response.array()); outputStream.flush(); if (success) { + Log.d(Config.LOGTAG, connection.getAccount().getJid().asBareJid() + ": successfully processed connection to candidate " + candidate.getHost() + ":" + candidate.getPort()); this.socket = socket; this.inputStream = inputStream; this.outputStream = outputStream; this.isEstablished = true; FileBackend.close(serverSocket); + } else { + this.socket.close(); } } else { socket.close(); @@ -175,6 +179,7 @@ public class JingleSocks5Transport extends JingleTransport { new Thread(() -> { InputStream fileInputStream = null; final PowerManager.WakeLock wakeLock = connection.getConnectionManager().createWakeLock("jingle_send_" + connection.getSessionId()); + long transmitted = 0; try { wakeLock.acquire(); MessageDigest digest = MessageDigest.getInstance("SHA-1"); @@ -187,7 +192,6 @@ public class JingleSocks5Transport extends JingleTransport { } final InputStream innerInputStream = AbstractConnectionManager.upgrade(file, fileInputStream); long size = file.getExpectedSize(); - long transmitted = 0; int count; byte[] buffer = new byte[8192]; while ((count = innerInputStream.read(buffer)) > 0) { @@ -202,7 +206,8 @@ public class JingleSocks5Transport extends JingleTransport { callback.onFileTransmitted(file); } } catch (Exception e) { - Log.d(Config.LOGTAG, connection.getAccount().getJid().asBareJid() + ": " + e.getMessage()); + final Account account = connection.getAccount(); + Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": failed sending file after " + transmitted + "/" + file.getExpectedSize() + " (" + socket.getInetAddress() + ":" + socket.getPort() + ")", e); callback.onFileTransferAborted(); } finally { FileBackend.close(fileInputStream); |