From e2324209ed7efd00eb4220c5877f9a1110fcd932 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Tue, 4 May 2021 19:04:01 +0200 Subject: [PATCH] make sure omemo sessions are verified if the the respective config flag is set --- .../crypto/axolotl/AxolotlService.java | 24 +++++++++++++++++++ .../xmpp/jingle/JingleRtpConnection.java | 21 +++++++++------- .../xmpp/jingle/stanzas/Reason.java | 10 ++++++++ 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java index e89eb4d13..c2d111e4b 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java @@ -1234,6 +1234,9 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { if (session == null) { throw new CryptoFailedException(String.format("No session found for %d", deviceId)); } + if (Config.REQUIRE_RTP_VERIFICATION) { + requireVerification(session); + } final ImmutableMap.Builder descriptionTransportBuilder = new ImmutableMap.Builder<>(); final OmemoVerification omemoVerification = new OmemoVerification(); omemoVerification.setDeviceId(deviceId); @@ -1283,6 +1286,9 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { final Element encrypted = child.findChildEnsureSingle(XmppAxolotlMessage.CONTAINERTAG, AxolotlService.PEP_PREFIX); final XmppAxolotlMessage xmppAxolotlMessage = XmppAxolotlMessage.fromElement(encrypted, from.asBareJid()); final XmppAxolotlSession session = getReceivingSession(xmppAxolotlMessage); + if (Config.REQUIRE_RTP_VERIFICATION) { + requireVerification(session); + } final XmppAxolotlMessage.XmppAxolotlPlaintextMessage plaintext = xmppAxolotlMessage.decrypt(session, getOwnDeviceId()); final Integer preKeyId = session.getPreKeyIdAndReset(); if (preKeyId != null) { @@ -1299,6 +1305,16 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { return new OmemoVerifiedPayload<>(omemoVerification, transportInfo); } + private static void requireVerification(final XmppAxolotlSession session) { + if (session.getTrust().isVerified()) { + return; + } + throw new NotVerifiedException(String.format( + "session with %s was not verified", + session.getFingerprint() + )); + } + public void prepareKeyTransportMessage(final Conversation conversation, final OnMessageCreatedCallback onMessageCreatedCallback) { executor.execute(new Runnable() { @Override @@ -1690,4 +1706,12 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { return payload; } } + + public static class NotVerifiedException extends SecurityException { + + public NotVerifiedException(String message) { + super(message); + } + + } } diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java index 80133268e..3fea3fee6 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java @@ -762,9 +762,7 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web } catch (final WebRTCWrapper.InitializationException e) { Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": unable to initialize WebRTC"); webRTCWrapper.close(); - sendJingleMessage("retract", id.with.asBareJid()); - transitionOrThrow(State.TERMINATED_APPLICATION_FAILURE); - this.finish(); + sendRetract(Reason.ofException(e)); return; } try { @@ -776,22 +774,27 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web } catch (final Exception e) { Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": unable to sendSessionInitiate", Throwables.getRootCause(e)); webRTCWrapper.close(); + final Reason reason = Reason.ofException(e); if (isInState(targetState)) { - sendSessionTerminate(Reason.FAILED_APPLICATION); + sendSessionTerminate(reason); } else { - sendJingleMessage("retract", id.with.asBareJid()); - transitionOrThrow(State.TERMINATED_APPLICATION_FAILURE); - this.finish(); + sendRetract(reason); } } } + private void sendRetract(final Reason reason) { + //TODO embed reason into retract + sendJingleMessage("retract", id.with.asBareJid()); + transitionOrThrow(reasonToState(reason)); + this.finish(); + } + private void sendSessionInitiate(final RtpContentMap rtpContentMap, final State targetState) { this.initiatorRtpContentMap = rtpContentMap; - this.transitionOrThrow(targetState); - //TODO do on background thread? final RtpContentMap outgoingContentMap = encryptSessionInitiate(rtpContentMap); final JinglePacket sessionInitiate = outgoingContentMap.toJinglePacket(JinglePacket.Action.SESSION_INITIATE, id.sessionId); + this.transitionOrThrow(targetState); send(sessionInitiate); } diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/Reason.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/Reason.java index c419045b0..365fda070 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/Reason.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/Reason.java @@ -3,7 +3,9 @@ package eu.siacs.conversations.xmpp.jingle.stanzas; import androidx.annotation.NonNull; import com.google.common.base.CaseFormat; +import com.google.common.base.Throwables; +import eu.siacs.conversations.crypto.axolotl.AxolotlService; import eu.siacs.conversations.xmpp.jingle.RtpContentMap; public enum Reason { @@ -51,4 +53,12 @@ public enum Reason { return FAILED_APPLICATION; } } + + public static Reason ofException(final Exception e) { + final Throwable root = Throwables.getRootCause(e); + if (root instanceof RuntimeException) { + return of((RuntimeException) root); + } + return FAILED_APPLICATION; + } } \ No newline at end of file