From e803f3ffa5ab1d451a30164f23c1d2cc3cb147b0 Mon Sep 17 00:00:00 2001 From: Christian Schneppe Date: Tue, 9 May 2017 21:14:35 +0200 Subject: make jingle implementation send file hash when using ft5 --- .../messenger/entities/DownloadableFile.java | 6 +- .../messenger/xmpp/jingle/JingleConnection.java | 100 ++++++++++++++------- .../xmpp/jingle/JingleInbandTransport.java | 6 +- .../xmpp/jingle/JingleSocks5Transport.java | 4 +- .../xmpp/jingle/stanzas/JinglePacket.java | 19 ++++ 5 files changed, 93 insertions(+), 42 deletions(-) (limited to 'src/main') diff --git a/src/main/java/de/pixart/messenger/entities/DownloadableFile.java b/src/main/java/de/pixart/messenger/entities/DownloadableFile.java index ee0694196..f0a3aa00c 100644 --- a/src/main/java/de/pixart/messenger/entities/DownloadableFile.java +++ b/src/main/java/de/pixart/messenger/entities/DownloadableFile.java @@ -9,7 +9,7 @@ public class DownloadableFile extends File { private static final long serialVersionUID = 2247012619505115863L; private long expectedSize = 0; - private String sha1sum; + private byte[] sha1sum; private byte[] aeskey; private byte[] iv = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, @@ -42,11 +42,11 @@ public class DownloadableFile extends File { this.expectedSize = size; } - public String getSha1Sum() { + public byte[] getSha1Sum() { return this.sha1sum; } - public void setSha1Sum(String sum) { + public void setSha1Sum(byte[] sum) { this.sha1sum = sum; } 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 1ca924834..bf92a2c30 100644 --- a/src/main/java/de/pixart/messenger/xmpp/jingle/JingleConnection.java +++ b/src/main/java/de/pixart/messenger/xmpp/jingle/JingleConnection.java @@ -1,5 +1,6 @@ package de.pixart.messenger.xmpp.jingle; +import android.util.Base64; import android.util.Log; import android.util.Pair; @@ -8,6 +9,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; import java.util.Iterator; import java.util.List; @@ -31,6 +33,7 @@ import de.pixart.messenger.parser.IqParser; import de.pixart.messenger.persistance.FileBackend; import de.pixart.messenger.services.AbstractConnectionManager; import de.pixart.messenger.services.XmppConnectionService; +import de.pixart.messenger.utils.CryptoHelper; import de.pixart.messenger.xml.Element; import de.pixart.messenger.xmpp.OnIqPacketReceived; import de.pixart.messenger.xmpp.jid.Jid; @@ -95,12 +98,16 @@ public class JingleConnection implements Transferable { } } }; + private byte[] expectedHash = new byte[0]; - final OnFileTransmissionStatusChanged onFileTransmissionSatusChanged = new OnFileTransmissionStatusChanged() { + final OnFileTransmissionStatusChanged onFileTransmissionStatusChanged = new OnFileTransmissionStatusChanged() { @Override public void onFileTransmitted(DownloadableFile file) { - if (responder.equals(account.getJid())) { + if (responding()) { + if (expectedHash.length > 0 && !Arrays.equals(expectedHash, file.getSha1Sum())) { + Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": hashes did not match"); + } sendSuccess(); mXmppConnectionService.getFileBackend().updateFileParams(message); mXmppConnectionService.databaseBackend.createMessage(message); @@ -114,6 +121,9 @@ public class JingleConnection implements Transferable { } } } else { + if (ftVersion == Content.Version.FT_5) { //older Conversations will break when receiving a session-info + sendHash(); + } if (message.getEncryption() == Message.ENCRYPTION_PGP) { account.getPgpDecryptionService().decrypt(message, false); } @@ -121,7 +131,7 @@ public class JingleConnection implements Transferable { file.delete(); } } - Log.d(Config.LOGTAG, "successfully transmitted file:" + file.getAbsolutePath() + " (" + file.getSha1Sum() + ")"); + Log.d(Config.LOGTAG, "successfully transmitted file:" + file.getAbsolutePath() + " (" + CryptoHelper.bytesToHex(file.getSha1Sum()) + ")"); if (message.getEncryption() != Message.ENCRYPTION_PGP) { mXmppConnectionService.getFileBackend().updateMediaScanner(file); } @@ -134,6 +144,14 @@ public class JingleConnection implements Transferable { } }; + private boolean responding() { + return responder.equals(account.getJid()); + } + + private boolean initiating() { + return initiator.equals(account.getJid()); + } + public InputStream getFileInputStream() { return this.mFileInputStream; } @@ -148,9 +166,9 @@ public class JingleConnection implements Transferable { public void success() { if (initiator.equals(account.getJid())) { Log.d(Config.LOGTAG, "we were initiating. sending file"); - transport.send(file, onFileTransmissionSatusChanged); + transport.send(file, onFileTransmissionStatusChanged); } else { - transport.receive(file, onFileTransmissionSatusChanged); + transport.receive(file, onFileTransmissionStatusChanged); Log.d(Config.LOGTAG, "we were responding. receiving file"); } } @@ -196,6 +214,18 @@ public class JingleConnection implements Transferable { } } else if (packet.isAction("session-accept")) { returnResult = receiveAccept(packet); + } else if (packet.isAction("session-info")) { + returnResult = true; + Element checksum = packet.getChecksum(); + Element file = checksum == null ? null : checksum.findChild("file"); + Element hash = file == null ? null : file.findChild("hash", "urn:xmpp:hashes:2"); + if (hash != null && "sha-1".equalsIgnoreCase(hash.getAttribute("algo"))) { + try { + this.expectedHash = Base64.decode(hash.getContent(), Base64.DEFAULT); + } catch (Exception e) { + this.expectedHash = new byte[0]; + } + } } else if (packet.isAction("transport-info")) { returnResult = receiveTransportInfo(packet); } else if (packet.isAction("transport-replace")) { @@ -503,6 +533,12 @@ public class JingleConnection implements Transferable { } } + private void sendHash() { + JinglePacket packet = this.bootstrapPacket("session-info"); + packet.addChecksum(file.getSha1Sum(), ftVersion.getNamespace()); + this.sendJinglePacket(packet); + } + private List getCandidatesAsElements() { List elements = new ArrayList<>(); for (JingleCandidate c : this.candidates) { @@ -657,7 +693,7 @@ public class JingleConnection implements Transferable { if (connection == null) { Log.d(Config.LOGTAG, "could not find suitable candidate"); this.disconnectSocks5Connections(); - if (this.initiator.equals(account.getJid())) { + if (initiating()) { this.sendFallbackToIbb(); } } else { @@ -701,12 +737,12 @@ public class JingleConnection implements Transferable { + " was a proxy. waiting for other party to activate"); } } else { - if (initiator.equals(account.getJid())) { + if (initiating()) { Log.d(Config.LOGTAG, "we were initiating. sending file"); - connection.send(file, onFileTransmissionSatusChanged); + connection.send(file, onFileTransmissionStatusChanged); } else { Log.d(Config.LOGTAG, "we were responding. receiving file"); - connection.receive(file, onFileTransmissionSatusChanged); + connection.receive(file, onFileTransmissionStatusChanged); } } } @@ -731,7 +767,7 @@ public class JingleConnection implements Transferable { } else if (connection.getCandidate().getPriority() == currentConnection .getCandidate().getPriority()) { // Log.d(Config.LOGTAG,"found two candidates with same priority"); - if (initiator.equals(account.getJid())) { + if (initiating()) { if (currentConnection.getCandidate().isOurs()) { connection = currentConnection; } @@ -781,7 +817,7 @@ public class JingleConnection implements Transferable { @Override public void established() { - JingleConnection.this.transport.send(file, onFileTransmissionSatusChanged); + JingleConnection.this.transport.send(file, onFileTransmissionStatusChanged); } }; @@ -802,7 +838,7 @@ public class JingleConnection implements Transferable { content.setTransportId(this.transportId); content.ibbTransport().setAttribute("block-size", this.ibbBlockSize); answer.setContent(content); - if (initiator.equals(account.getJid())) { + if (initiating()) { this.sendJinglePacket(answer, new OnIqPacketReceived() { @Override public void onIqPacketReceived(Account account, IqPacket packet) { @@ -813,7 +849,7 @@ public class JingleConnection implements Transferable { } }); } else { - this.transport.receive(file, onFileTransmissionSatusChanged); + this.transport.receive(file, onFileTransmissionStatusChanged); this.sendJinglePacket(answer); } return true; @@ -831,10 +867,10 @@ public class JingleConnection implements Transferable { } this.transport = new JingleInbandTransport(this, this.transportId, this.ibbBlockSize); //might be receive instead if we are not initiating - if (initiator.equals(account.getJid())) { + if (initiating()) { this.transport.connect(onIbbTransportConnected); } else { - this.transport.receive(file, onFileTransmissionSatusChanged); + this.transport.receive(file, onFileTransmissionStatusChanged); } return true; } else { @@ -843,14 +879,18 @@ public class JingleConnection implements Transferable { } private void receiveSuccess() { - this.mJingleStatus = JINGLE_STATUS_FINISHED; - this.mXmppConnectionService.markMessage(this.message, Message.STATUS_SEND_RECEIVED); - this.disconnectSocks5Connections(); - if (this.transport != null && this.transport instanceof JingleInbandTransport) { - this.transport.disconnect(); + if (initiating()) { + this.mJingleStatus = JINGLE_STATUS_FINISHED; + this.mXmppConnectionService.markMessage(this.message, Message.STATUS_SEND_RECEIVED); + this.disconnectSocks5Connections(); + if (this.transport != null && this.transport instanceof JingleInbandTransport) { + this.transport.disconnect(); + } + this.message.setTransferable(null); + this.mJingleConnectionManager.finishConnection(this); + } else { + Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": received session-terminate/success while responding"); } - this.message.setTransferable(null); - this.mJingleConnectionManager.finishConnection(this); } public void cancel() { @@ -860,7 +900,7 @@ public class JingleConnection implements Transferable { } this.sendCancel(); this.mJingleConnectionManager.finishConnection(this); - if (this.responder.equals(account.getJid())) { + if (responding()) { this.message.setTransferable(new TransferablePlaceholder(Transferable.STATUS_FAILED)); if (this.file != null) { file.delete(); @@ -886,7 +926,7 @@ public class JingleConnection implements Transferable { FileBackend.close(mFileInputStream); FileBackend.close(mFileOutputStream); if (this.message != null) { - if (this.responder.equals(account.getJid())) { + if (responding()) { this.message.setTransferable(new TransferablePlaceholder(Transferable.STATUS_FAILED)); if (this.file != null) { file.delete(); @@ -992,14 +1032,6 @@ public class JingleConnection implements Transferable { this.sendJinglePacket(packet); } - public Jid getInitiator() { - return this.initiator; - } - - public Jid getResponder() { - return this.responder; - } - public int getJingleStatus() { return this.mJingleStatus; } @@ -1051,9 +1083,9 @@ public class JingleConnection implements Transferable { } interface OnProxyActivated { - public void success(); + void success(); - public void failed(); + void failed(); } public boolean hasTransportId(String sid) { diff --git a/src/main/java/de/pixart/messenger/xmpp/jingle/JingleInbandTransport.java b/src/main/java/de/pixart/messenger/xmpp/jingle/JingleInbandTransport.java index fbf494295..33750c16a 100644 --- a/src/main/java/de/pixart/messenger/xmpp/jingle/JingleInbandTransport.java +++ b/src/main/java/de/pixart/messenger/xmpp/jingle/JingleInbandTransport.java @@ -166,7 +166,7 @@ public class JingleInbandTransport extends JingleTransport { int count = fileInputStream.read(buffer); if (count == -1) { sendClose(); - file.setSha1Sum(CryptoHelper.bytesToHex(digest.digest())); + file.setSha1Sum(digest.digest()); this.onFileTransmissionStatusChanged.onFileTransmitted(file); fileInputStream.close(); return; @@ -193,7 +193,7 @@ public class JingleInbandTransport extends JingleTransport { connection.updateProgress((int) ((((double) (this.fileSize - this.remainingSize)) / this.fileSize) * 100)); } else { sendClose(); - file.setSha1Sum(CryptoHelper.bytesToHex(digest.digest())); + file.setSha1Sum(digest.digest()); this.onFileTransmissionStatusChanged.onFileTransmitted(file); fileInputStream.close(); } @@ -214,7 +214,7 @@ public class JingleInbandTransport extends JingleTransport { this.fileOutputStream.write(buffer); this.digest.update(buffer); if (this.remainingSize <= 0) { - file.setSha1Sum(CryptoHelper.bytesToHex(digest.digest())); + file.setSha1Sum(digest.digest()); fileOutputStream.flush(); fileOutputStream.close(); this.onFileTransmissionStatusChanged.onFileTransmitted(file); 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 57d1afeba..aa30d69a5 100644 --- a/src/main/java/de/pixart/messenger/xmpp/jingle/JingleSocks5Transport.java +++ b/src/main/java/de/pixart/messenger/xmpp/jingle/JingleSocks5Transport.java @@ -112,7 +112,7 @@ public class JingleSocks5Transport extends JingleTransport { connection.updateProgress((int) ((((double) transmitted) / size) * 100)); } outputStream.flush(); - file.setSha1Sum(CryptoHelper.bytesToHex(digest.digest())); + file.setSha1Sum(digest.digest()); if (callback != null) { callback.onFileTransmitted(file); } @@ -168,7 +168,7 @@ public class JingleSocks5Transport extends JingleTransport { } fileOutputStream.flush(); fileOutputStream.close(); - file.setSha1Sum(CryptoHelper.bytesToHex(digest.digest())); + file.setSha1Sum(digest.digest()); callback.onFileTransmitted(file); } catch (Exception e) { Log.d(Config.LOGTAG, connection.getAccount().getJid().toBareJid() + ": " + e.getMessage()); diff --git a/src/main/java/de/pixart/messenger/xmpp/jingle/stanzas/JinglePacket.java b/src/main/java/de/pixart/messenger/xmpp/jingle/stanzas/JinglePacket.java index de856772a..3f7cc8e5b 100644 --- a/src/main/java/de/pixart/messenger/xmpp/jingle/stanzas/JinglePacket.java +++ b/src/main/java/de/pixart/messenger/xmpp/jingle/stanzas/JinglePacket.java @@ -1,5 +1,7 @@ package de.pixart.messenger.xmpp.jingle.stanzas; +import android.util.Base64; + import de.pixart.messenger.xml.Element; import de.pixart.messenger.xmpp.jid.Jid; import de.pixart.messenger.xmpp.stanzas.IqPacket; @@ -7,6 +9,7 @@ import de.pixart.messenger.xmpp.stanzas.IqPacket; public class JinglePacket extends IqPacket { Content content = null; Reason reason = null; + Element checksum = null; Element jingle = new Element("jingle"); @Override @@ -24,6 +27,7 @@ public class JinglePacket extends IqPacket { this.reason.setChildren(reasonElement.getChildren()); this.reason.setAttributes(reasonElement.getAttributes()); } + this.checksum = child.findChild("checksum"); this.jingle.setAttributes(child.getAttributes()); } return child; @@ -50,6 +54,10 @@ public class JinglePacket extends IqPacket { return this.reason; } + public Element getChecksum() { + return this.checksum; + } + private void build() { this.children.clear(); this.jingle.clearChildren(); @@ -60,6 +68,9 @@ public class JinglePacket extends IqPacket { if (this.reason != null) { jingle.addChild(this.reason); } + if (this.checksum != null) { + jingle.addChild(checksum); + } this.children.add(jingle); this.setAttribute("type", "set"); } @@ -93,4 +104,12 @@ public class JinglePacket extends IqPacket { public boolean isAction(String action) { return action.equalsIgnoreCase(this.getAction()); } + + public void addChecksum(byte[] sha1Sum, String namespace) { + this.checksum = new Element("checksum", namespace); + checksum.setAttribute("creator", "initiator"); + checksum.setAttribute("name", "a-file-offer"); + Element hash = checksum.addChild("file").addChild("hash", "urn:xmpp:hashes:2"); + hash.setAttribute("algo", "sha-1").setContent(Base64.encodeToString(sha1Sum, Base64.NO_WRAP)); + } } -- cgit v1.2.3