aboutsummaryrefslogtreecommitdiffstats
path: root/src/eu/siacs/conversations/xmpp
diff options
context:
space:
mode:
authoriNPUTmice <daniel@gultsch.de>2014-06-20 17:30:19 +0200
committeriNPUTmice <daniel@gultsch.de>2014-06-20 17:30:19 +0200
commit1cf055d2fdbaa881cfc8ead6b78dc744e9dbe596 (patch)
tree51c0a3463ff3d5f005aeb6dccf6c50d05fddab42 /src/eu/siacs/conversations/xmpp
parentbeafb06b6a59649a4c314db820f5ce30be120e7c (diff)
not working version of otr file transfer
Diffstat (limited to '')
-rw-r--r--src/eu/siacs/conversations/xmpp/XmppConnection.java12
-rw-r--r--src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java24
-rw-r--r--src/eu/siacs/conversations/xmpp/jingle/JingleFile.java26
-rw-r--r--src/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java40
-rw-r--r--src/eu/siacs/conversations/xmpp/jingle/JingleTransport.java59
-rw-r--r--src/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java8
6 files changed, 137 insertions, 32 deletions
diff --git a/src/eu/siacs/conversations/xmpp/XmppConnection.java b/src/eu/siacs/conversations/xmpp/XmppConnection.java
index f2c0962a..2447b49b 100644
--- a/src/eu/siacs/conversations/xmpp/XmppConnection.java
+++ b/src/eu/siacs/conversations/xmpp/XmppConnection.java
@@ -37,6 +37,7 @@ import android.os.PowerManager.WakeLock;
import android.os.SystemClock;
import android.util.Log;
import eu.siacs.conversations.entities.Account;
+import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.utils.CryptoHelper;
import eu.siacs.conversations.utils.DNSHelper;
import eu.siacs.conversations.utils.zlib.ZLibOutputStream;
@@ -63,7 +64,7 @@ public class XmppConnection implements Runnable {
private WakeLock wakeLock;
- private SecureRandom random = new SecureRandom();
+ private SecureRandom mRandom;
private Socket socket;
private XmlReader tagReader;
@@ -100,9 +101,10 @@ public class XmppConnection implements Runnable {
private OnTLSExceptionReceived tlsListener = null;
private OnBindListener bindListener = null;
- public XmppConnection(Account account, PowerManager pm) {
+ public XmppConnection(Account account, XmppConnectionService service) {
+ this.mRandom = service.getRNG();
this.account = account;
- this.wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
+ this.wakeLock = service.getPowerManager().newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
account.getJid());
tagWriter = new TagWriter();
}
@@ -248,7 +250,7 @@ public class XmppConnection implements Runnable {
response.setAttribute("xmlns",
"urn:ietf:params:xml:ns:xmpp-sasl");
response.setContent(CryptoHelper.saslDigestMd5(account,
- challange));
+ challange,mRandom));
tagWriter.writeElement(response);
} else if (nextTag.isStart("enabled")) {
this.stanzasSent = 0;
@@ -772,7 +774,7 @@ public class XmppConnection implements Runnable {
}
private String nextRandomId() {
- return new BigInteger(50, random).toString(32);
+ return new BigInteger(50, mRandom).toString(32);
}
public void sendIqPacket(IqPacket packet, OnIqPacketReceived callback) {
diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java b/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java
index 8f88688a..85110c38 100644
--- a/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java
+++ b/src/eu/siacs/conversations/xmpp/jingle/JingleConnection.java
@@ -9,11 +9,11 @@ import java.util.Map.Entry;
import android.graphics.BitmapFactory;
import android.util.Log;
-
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.services.XmppConnectionService;
+import eu.siacs.conversations.utils.CryptoHelper;
import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.OnIqPacketReceived;
import eu.siacs.conversations.xmpp.jingle.stanzas.Content;
@@ -24,7 +24,7 @@ import eu.siacs.conversations.xmpp.stanzas.IqPacket;
public class JingleConnection {
private final String[] extensions = {"webp","jpeg","jpg","png"};
- private final String[] cryptoExtensions = {"pgp","gpg"};
+ private final String[] cryptoExtensions = {"pgp","gpg","otr"};
private JingleConnectionManager mJingleConnectionManager;
private XmppConnectionService mXmppConnectionService;
@@ -244,6 +244,7 @@ public class JingleConnection {
Element fileNameElement = fileOffer.findChild("name");
if (fileNameElement!=null) {
boolean supportedFile = false;
+ Log.d("xmppService","file offer: "+fileNameElement.getContent());
String[] filename = fileNameElement.getContent().toLowerCase().split("\\.");
if (Arrays.asList(this.extensions).contains(filename[filename.length - 1])) {
supportedFile = true;
@@ -251,7 +252,12 @@ public class JingleConnection {
if (filename.length == 3) {
if (Arrays.asList(this.extensions).contains(filename[filename.length -2])) {
supportedFile = true;
- this.message.setEncryption(Message.ENCRYPTION_PGP);
+ if (filename[filename.length - 1].equals("otr")) {
+ Log.d("xmppService","receiving otr file");
+ this.message.setEncryption(Message.ENCRYPTION_OTR);
+ } else {
+ this.message.setEncryption(Message.ENCRYPTION_PGP);
+ }
}
}
}
@@ -269,6 +275,9 @@ public class JingleConnection {
this.mXmppConnectionService.updateUi(conversation, true);
}
this.file = this.mXmppConnectionService.getFileBackend().getJingleFile(message,false);
+ if (message.getEncryption() == Message.ENCRYPTION_OTR) {
+ this.file.setKey(conversation.getSymmetricKey());
+ }
this.file.setExpectedSize(size);
} else {
this.sendCancel();
@@ -287,7 +296,14 @@ public class JingleConnection {
if (message.getType() == Message.TYPE_IMAGE) {
content.setTransportId(this.transportId);
this.file = this.mXmppConnectionService.getFileBackend().getJingleFile(message,false);
- content.setFileOffer(this.file);
+ if (message.getEncryption() == Message.ENCRYPTION_OTR) {
+ Conversation conversation = this.message.getConversation();
+ this.mXmppConnectionService.renewSymmetricKey(conversation);
+ content.setFileOffer(this.file, true);
+ this.file.setKey(conversation.getSymmetricKey());
+ } else {
+ content.setFileOffer(this.file,false);
+ }
this.transportId = this.mJingleConnectionManager.nextRandomId();
content.setTransportId(this.transportId);
content.socks5transport().setChildren(getCandidatesAsElements());
diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleFile.java b/src/eu/siacs/conversations/xmpp/jingle/JingleFile.java
index 21cbd716..fd366754 100644
--- a/src/eu/siacs/conversations/xmpp/jingle/JingleFile.java
+++ b/src/eu/siacs/conversations/xmpp/jingle/JingleFile.java
@@ -1,6 +1,12 @@
package eu.siacs.conversations.xmpp.jingle;
import java.io.File;
+import java.security.Key;
+
+import javax.crypto.spec.SecretKeySpec;
+
+import eu.siacs.conversations.utils.CryptoHelper;
+import android.util.Log;
public class JingleFile extends File {
@@ -8,6 +14,7 @@ public class JingleFile extends File {
private long expectedSize = 0;
private String sha1sum;
+ private Key aeskey;
public JingleFile(String path) {
super(path);
@@ -32,4 +39,23 @@ public class JingleFile extends File {
public void setSha1Sum(String sum) {
this.sha1sum = sum;
}
+
+ public void setKey(byte[] key) {
+ Log.d("xmppService","using aes key "+CryptoHelper.bytesToHex(key));
+ if (key.length>=32) {
+ byte[] secretKey = new byte[32];
+ System.arraycopy(key, 0, secretKey, 0, 32);
+ this.aeskey = new SecretKeySpec(key, "AES");
+ } else if (key.length>=16) {
+ byte[] secretKey = new byte[15];
+ System.arraycopy(key, 0, secretKey, 0, 16);
+ this.aeskey = new SecretKeySpec(key, "AES");
+ } else {
+ Log.d("xmppService","weird key");
+ }
+ }
+
+ public Key getKey() {
+ return this.aeskey;
+ }
}
diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java b/src/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java
index 0f2d4cae..838c7d5f 100644
--- a/src/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java
+++ b/src/eu/siacs/conversations/xmpp/jingle/JingleSocks5Transport.java
@@ -12,6 +12,7 @@ import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
+import android.util.Log;
import eu.siacs.conversations.utils.CryptoHelper;
public class JingleSocks5Transport extends JingleTransport {
@@ -90,19 +91,23 @@ public class JingleSocks5Transport extends JingleTransport {
@Override
public void run() {
- FileInputStream fileInputStream = null;
+ InputStream fileInputStream = null;
try {
MessageDigest digest = MessageDigest.getInstance("SHA-1");
digest.reset();
- fileInputStream = new FileInputStream(file);
+ fileInputStream = getInputStream(file);
int count;
+ long txbytes = 0;
byte[] buffer = new byte[8192];
- while ((count = fileInputStream.read(buffer)) > 0) {
+ while ((count = fileInputStream.read(buffer)) != -1) {
+ txbytes += count;
outputStream.write(buffer, 0, count);
digest.update(buffer, 0, count);
+ Log.d("xmppService","tx bytes: "+txbytes);
}
outputStream.flush();
file.setSha1Sum(CryptoHelper.bytesToHex(digest.digest()));
+ //outputStream.close();
if (callback!=null) {
callback.onFileTransmitted(file);
}
@@ -110,8 +115,7 @@ public class JingleSocks5Transport extends JingleTransport {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ Log.d("xmppService","io exception: "+e.getMessage());
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
@@ -141,36 +145,30 @@ public class JingleSocks5Transport extends JingleTransport {
inputStream.skip(45);
file.getParentFile().mkdirs();
file.createNewFile();
- FileOutputStream fileOutputStream = new FileOutputStream(file);
+ OutputStream fileOutputStream = getOutputStream(file);
long remainingSize = file.getExpectedSize();
byte[] buffer = new byte[8192];
int count = buffer.length;
- while(remainingSize > 0) {
- if (remainingSize<=count) {
- count = (int) remainingSize;
- }
- count = inputStream.read(buffer, 0, count);
- if (count==-1) {
- // TODO throw exception
- } else {
+ //while(remainingSize > 0) {
+ while((count = inputStream.read(buffer)) > 0) {
+ Log.d("xmppService","remaining size: "+remainingSize+" reading "+count+" bytes");
+ count = inputStream.read(buffer);
+ if (count!=-1) {
fileOutputStream.write(buffer, 0, count);
digest.update(buffer, 0, count);
- remainingSize-=count;
}
+ remainingSize-=count;
}
fileOutputStream.flush();
fileOutputStream.close();
file.setSha1Sum(CryptoHelper.bytesToHex(digest.digest()));
callback.onFileTransmitted(file);
} catch (FileNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ Log.d("xmppService","file not found exception");
} catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ Log.d("xmppService","io exception: "+e.getMessage());
} catch (NoSuchAlgorithmException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ Log.d("xmppService","no such algo"+e.getMessage());
}
}
}).start();
diff --git a/src/eu/siacs/conversations/xmpp/jingle/JingleTransport.java b/src/eu/siacs/conversations/xmpp/jingle/JingleTransport.java
index 290bb5d3..b96fefed 100644
--- a/src/eu/siacs/conversations/xmpp/jingle/JingleTransport.java
+++ b/src/eu/siacs/conversations/xmpp/jingle/JingleTransport.java
@@ -1,7 +1,66 @@
package eu.siacs.conversations.xmpp.jingle;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+
+import javax.crypto.Cipher;
+import javax.crypto.CipherOutputStream;
+import javax.crypto.CipherInputStream;
+import javax.crypto.NoSuchPaddingException;
+
+import android.util.Log;
+
public abstract class JingleTransport {
public abstract void connect(final OnTransportConnected callback);
public abstract void receive(final JingleFile file, final OnFileTransmitted callback);
public abstract void send(final JingleFile file, final OnFileTransmitted callback);
+
+ protected InputStream getInputStream(JingleFile file) throws FileNotFoundException {
+ if (file.getKey() == null) {
+ return new FileInputStream(file);
+ } else {
+ try {
+ Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
+ cipher.init(Cipher.ENCRYPT_MODE, file.getKey());
+ Log.d("xmppService","opening encrypted input stream");
+ return new CipherInputStream(new FileInputStream(file), cipher);
+ } catch (NoSuchAlgorithmException e) {
+ Log.d("xmppService","no such algo: "+e.getMessage());
+ return null;
+ } catch (NoSuchPaddingException e) {
+ Log.d("xmppService","no such padding: "+e.getMessage());
+ return null;
+ } catch (InvalidKeyException e) {
+ Log.d("xmppService","invalid key: "+e.getMessage());
+ return null;
+ }
+ }
+ }
+
+ protected OutputStream getOutputStream(JingleFile file) throws FileNotFoundException {
+ if (file.getKey() == null) {
+ return new FileOutputStream(file);
+ } else {
+ try {
+ Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
+ cipher.init(Cipher.DECRYPT_MODE, file.getKey());
+ Log.d("xmppService","opening encrypted output stream");
+ return new CipherOutputStream(new FileOutputStream(file), cipher);
+ } catch (NoSuchAlgorithmException e) {
+ Log.d("xmppService","no such algo: "+e.getMessage());
+ return null;
+ } catch (NoSuchPaddingException e) {
+ Log.d("xmppService","no such padding: "+e.getMessage());
+ return null;
+ } catch (InvalidKeyException e) {
+ Log.d("xmppService","invalid key: "+e.getMessage());
+ return null;
+ }
+ }
+ }
}
diff --git a/src/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java b/src/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java
index abede91a..494ff0d6 100644
--- a/src/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java
+++ b/src/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java
@@ -25,12 +25,16 @@ public class Content extends Element {
this.transportId = sid;
}
- public void setFileOffer(JingleFile actualFile) {
+ public void setFileOffer(JingleFile actualFile, boolean otr) {
Element description = this.addChild("description", "urn:xmpp:jingle:apps:file-transfer:3");
Element offer = description.addChild("offer");
Element file = offer.addChild("file");
file.addChild("size").setContent(""+actualFile.getSize());
- file.addChild("name").setContent(actualFile.getName());
+ if (otr) {
+ file.addChild("name").setContent(actualFile.getName()+".otr");
+ } else {
+ file.addChild("name").setContent(actualFile.getName());
+ }
}
public Element getFileOffer() {