implemented support for for jingle encrypted transports (XEP-0396)
This commit is contained in:
		
							parent
							
								
									ff4d127b6f
								
							
						
					
					
						commit
						7ec1b443ab
					
				|  | @ -101,8 +101,8 @@ public final class Config { | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     public static final boolean DISABLE_PROXY_LOOKUP = false; //useful to debug ibb |     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 DISABLE_HTTP_UPLOAD = true; | ||||||
|     public static final boolean EXTENDED_SM_LOGGING = false; // log stanza counts |     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 |     public static final boolean BACKGROUND_STANZA_LOGGING = false; //log all stanzas that were received while the app is in background | ||||||
|     public static final boolean RESET_ATTEMPT_COUNT_ON_NETWORK_CHANGE = true; //setting to true might increase power consumption |     public static final boolean RESET_ATTEMPT_COUNT_ON_NETWORK_CHANGE = true; //setting to true might increase power consumption | ||||||
|  |  | ||||||
|  | @ -29,6 +29,8 @@ public abstract class AbstractGenerator { | ||||||
| 			Content.Version.FT_5.getNamespace(), | 			Content.Version.FT_5.getNamespace(), | ||||||
| 			Namespace.JINGLE_TRANSPORTS_S5B, | 			Namespace.JINGLE_TRANSPORTS_S5B, | ||||||
| 			Namespace.JINGLE_TRANSPORTS_IBB, | 			Namespace.JINGLE_TRANSPORTS_IBB, | ||||||
|  | 			Namespace.JINGLE_ENCRYPTED_TRANSPORT, | ||||||
|  | 			Namespace.JINGLE_ENCRYPTED_TRANSPORT_OMEMO, | ||||||
| 			"http://jabber.org/protocol/muc", | 			"http://jabber.org/protocol/muc", | ||||||
| 			"jabber:x:conference", | 			"jabber:x:conference", | ||||||
| 			Namespace.OOB, | 			Namespace.OOB, | ||||||
|  |  | ||||||
|  | @ -30,4 +30,6 @@ public final class Namespace { | ||||||
| 	public static final String PING = "urn:xmpp:ping"; | 	public static final String PING = "urn:xmpp:ping"; | ||||||
| 	public static final String PUSH = "urn:xmpp:push:0"; | 	public static final String PUSH = "urn:xmpp:push:0"; | ||||||
| 	public static final String COMMANDS = "http://jabber.org/protocol/commands"; | 	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"; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -43,6 +43,8 @@ import rocks.xmpp.addr.Jid; | ||||||
| 
 | 
 | ||||||
| public class JingleConnection implements Transferable { | public class JingleConnection implements Transferable { | ||||||
| 
 | 
 | ||||||
|  |     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_INITIATED = 0; | ||||||
|     private static final int JINGLE_STATUS_ACCEPTED = 1; |     private static final int JINGLE_STATUS_ACCEPTED = 1; | ||||||
|     private static final int JINGLE_STATUS_FINISHED = 4; |     private static final int JINGLE_STATUS_FINISHED = 4; | ||||||
|  | @ -72,6 +74,7 @@ public class JingleConnection implements Transferable { | ||||||
|     private String contentName; |     private String contentName; | ||||||
|     private String contentCreator; |     private String contentCreator; | ||||||
|     private Transport initialTransport; |     private Transport initialTransport; | ||||||
|  |     private boolean remoteSupportsOmemoJet; | ||||||
| 
 | 
 | ||||||
|     private int mProgress = 0; |     private int mProgress = 0; | ||||||
| 
 | 
 | ||||||
|  | @ -295,8 +298,10 @@ public class JingleConnection implements Transferable { | ||||||
|         this.contentName = this.mJingleConnectionManager.nextRandomId(); |         this.contentName = this.mJingleConnectionManager.nextRandomId(); | ||||||
|         this.message = message; |         this.message = message; | ||||||
|         this.account = message.getConversation().getAccount(); |         this.account = message.getConversation().getAccount(); | ||||||
|         upgradeNamespace(); |         final List<String> remoteFeatures = getRemoteFeatures(); | ||||||
|         this.initialTransport = getRemoteFeatures().contains(Namespace.JINGLE_TRANSPORTS_S5B) ? Transport.SOCKS : Transport.IBB; |         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.message.setTransferable(this); | ||||||
|         this.mStatus = Transferable.STATUS_UPLOADING; |         this.mStatus = Transferable.STATUS_UPLOADING; | ||||||
|         this.initiator = this.account.getJid(); |         this.initiator = this.account.getJid(); | ||||||
|  | @ -356,11 +361,10 @@ public class JingleConnection implements Transferable { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private void upgradeNamespace() { |     private void upgradeNamespace(List<String> remoteFeatures) { | ||||||
|         List<String> features = getRemoteFeatures(); |         if (remoteFeatures.contains(Content.Version.FT_5.getNamespace())) { | ||||||
|         if (features.contains(Content.Version.FT_5.getNamespace())) { |  | ||||||
|             this.ftVersion = Content.Version.FT_5; |             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; |             this.ftVersion = Content.Version.FT_4; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -430,6 +434,13 @@ public class JingleConnection implements Transferable { | ||||||
| 
 | 
 | ||||||
|         if (fileOffer != null) { |         if (fileOffer != null) { | ||||||
|             Element encrypted = fileOffer.findChild("encrypted", AxolotlService.PEP_PREFIX); |             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) { |             if (encrypted != null) { | ||||||
|                 this.mXmppAxolotlMessage = XmppAxolotlMessage.fromElement(encrypted, packet.getFrom().asBareJid()); |                 this.mXmppAxolotlMessage = XmppAxolotlMessage.fromElement(encrypted, packet.getFrom().asBareJid()); | ||||||
|             } |             } | ||||||
|  | @ -520,7 +531,18 @@ public class JingleConnection implements Transferable { | ||||||
|                 this.file.setKey(mXmppAxolotlMessage.getInnerKey()); |                 this.file.setKey(mXmppAxolotlMessage.getInnerKey()); | ||||||
|                 this.file.setIv(mXmppAxolotlMessage.getIV()); |                 this.file.setIv(mXmppAxolotlMessage.getIV()); | ||||||
|                 this.file.setExpectedSize(file.getSize() + 16); |                 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 { |             } else { | ||||||
|                 this.file.setExpectedSize(file.getSize()); |                 this.file.setExpectedSize(file.getSize()); | ||||||
|                 content.setFileOffer(this.file, false, this.ftVersion); |                 content.setFileOffer(this.file, false, this.ftVersion); | ||||||
|  | @ -754,6 +776,8 @@ public class JingleConnection implements Transferable { | ||||||
|                 this.sendFallbackToIbb(); |                 this.sendFallbackToIbb(); | ||||||
|             } |             } | ||||||
|         } else { |         } else { | ||||||
|  |             final JingleCandidate candidate = connection.getCandidate(); | ||||||
|  |             Log.d(Config.LOGTAG, account.getJid().asBareJid()+": elected candidate "+candidate.getHost()+":"+candidate.getPort()); | ||||||
|             this.mJingleStatus = JINGLE_STATUS_TRANSMITTING; |             this.mJingleStatus = JINGLE_STATUS_TRANSMITTING; | ||||||
|             if (connection.needsActivation()) { |             if (connection.needsActivation()) { | ||||||
|                 if (connection.getCandidate().isOurs()) { |                 if (connection.getCandidate().isOurs()) { | ||||||
|  |  | ||||||
|  | @ -16,6 +16,7 @@ import java.security.MessageDigest; | ||||||
| import java.security.NoSuchAlgorithmException; | import java.security.NoSuchAlgorithmException; | ||||||
| 
 | 
 | ||||||
| import eu.siacs.conversations.Config; | import eu.siacs.conversations.Config; | ||||||
|  | import eu.siacs.conversations.entities.Account; | ||||||
| import eu.siacs.conversations.entities.DownloadableFile; | import eu.siacs.conversations.entities.DownloadableFile; | ||||||
| import eu.siacs.conversations.persistance.FileBackend; | import eu.siacs.conversations.persistance.FileBackend; | ||||||
| import eu.siacs.conversations.services.AbstractConnectionManager; | import eu.siacs.conversations.services.AbstractConnectionManager; | ||||||
|  | @ -134,11 +135,14 @@ public class JingleSocks5Transport extends JingleTransport { | ||||||
|             outputStream.write(response.array()); |             outputStream.write(response.array()); | ||||||
|             outputStream.flush(); |             outputStream.flush(); | ||||||
|             if (success) { |             if (success) { | ||||||
|  |                 Log.d(Config.LOGTAG,connection.getAccount().getJid().asBareJid()+": successfully processed connection to candidate "+candidate.getHost()+":"+candidate.getPort()); | ||||||
|                 this.socket = socket; |                 this.socket = socket; | ||||||
|                 this.inputStream = inputStream; |                 this.inputStream = inputStream; | ||||||
|                 this.outputStream = outputStream; |                 this.outputStream = outputStream; | ||||||
|                 this.isEstablished = true; |                 this.isEstablished = true; | ||||||
|                 FileBackend.close(serverSocket); |                 FileBackend.close(serverSocket); | ||||||
|  |             } else { | ||||||
|  |                 this.socket.close(); | ||||||
|             } |             } | ||||||
|         } else { |         } else { | ||||||
|             socket.close(); |             socket.close(); | ||||||
|  | @ -174,6 +178,7 @@ public class JingleSocks5Transport extends JingleTransport { | ||||||
|         new Thread(() -> { |         new Thread(() -> { | ||||||
|             InputStream fileInputStream = null; |             InputStream fileInputStream = null; | ||||||
|             final PowerManager.WakeLock wakeLock = connection.getConnectionManager().createWakeLock("jingle_send_" + connection.getSessionId()); |             final PowerManager.WakeLock wakeLock = connection.getConnectionManager().createWakeLock("jingle_send_" + connection.getSessionId()); | ||||||
|  |             long transmitted = 0; | ||||||
|             try { |             try { | ||||||
|                 wakeLock.acquire(); |                 wakeLock.acquire(); | ||||||
|                 MessageDigest digest = MessageDigest.getInstance("SHA-1"); |                 MessageDigest digest = MessageDigest.getInstance("SHA-1"); | ||||||
|  | @ -186,7 +191,6 @@ public class JingleSocks5Transport extends JingleTransport { | ||||||
|                 } |                 } | ||||||
|                 final InputStream innerInputStream = AbstractConnectionManager.upgrade(file, fileInputStream); |                 final InputStream innerInputStream = AbstractConnectionManager.upgrade(file, fileInputStream); | ||||||
|                 long size = file.getExpectedSize(); |                 long size = file.getExpectedSize(); | ||||||
|                 long transmitted = 0; |  | ||||||
|                 int count; |                 int count; | ||||||
|                 byte[] buffer = new byte[8192]; |                 byte[] buffer = new byte[8192]; | ||||||
|                 while ((count = innerInputStream.read(buffer)) > 0) { |                 while ((count = innerInputStream.read(buffer)) > 0) { | ||||||
|  | @ -201,7 +205,8 @@ public class JingleSocks5Transport extends JingleTransport { | ||||||
|                     callback.onFileTransmitted(file); |                     callback.onFileTransmitted(file); | ||||||
|                 } |                 } | ||||||
|             } catch (Exception e) { |             } 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(); |                 callback.onFileTransferAborted(); | ||||||
|             } finally { |             } finally { | ||||||
|                 FileBackend.close(fileInputStream); |                 FileBackend.close(fileInputStream); | ||||||
|  |  | ||||||
|  | @ -873,4 +873,5 @@ | ||||||
|   <string name="not_a_backup_file">A kiválasztott fájl nem a Conversations biztonsági mentése</string> |   <string name="not_a_backup_file">A kiválasztott fájl nem a Conversations biztonsági mentése</string> | ||||||
|   <string name="account_already_setup">Ez a fiók már be lett állítva</string> |   <string name="account_already_setup">Ez a fiók már be lett állítva</string> | ||||||
|   <string name="please_enter_password">Kérem, adja meg a fiókhoz tartozó jelszót</string> |   <string name="please_enter_password">Kérem, adja meg a fiókhoz tartozó jelszót</string> | ||||||
|  |   <string name="unable_to_perform_this_action">Nem sikerült ezt a cselekvést elvégezni</string> | ||||||
| </resources> | </resources> | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Daniel Gultsch
						Daniel Gultsch