Change summary
src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java | 24
src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java | 21
src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/Reason.java | 10
3 files changed, 46 insertions(+), 9 deletions(-)
Detailed changes
@@ -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<String, RtpContentMap.DescriptionTransport> 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);
+ }
+
+ }
}
@@ -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);
}
@@ -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;
+ }
}