aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/de
diff options
context:
space:
mode:
authorChristian Schneppe <christian@pix-art.de>2019-09-06 22:01:42 +0200
committerChristian Schneppe <christian@pix-art.de>2019-09-06 22:01:42 +0200
commitc7629a60933ac61d6c38c1adb4a97c7d336514c4 (patch)
treeb28ce9893f3a2aa5e911ce495992c540a73729a2 /src/main/java/de
parentf8a94ec52e84a4903b55b6e456e6e7aa4a77d2be (diff)
implemented support for for jingle encrypted transports (XEP-0396)
Diffstat (limited to 'src/main/java/de')
-rw-r--r--src/main/java/de/pixart/messenger/Config.java2
-rw-r--r--src/main/java/de/pixart/messenger/generator/AbstractGenerator.java2
-rw-r--r--src/main/java/de/pixart/messenger/utils/Namespace.java2
-rw-r--r--src/main/java/de/pixart/messenger/xmpp/jingle/JingleConnection.java38
-rw-r--r--src/main/java/de/pixart/messenger/xmpp/jingle/JingleSocks5Transport.java9
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);