make sure omemo sessions are verified if the the respective config flag is set

This commit is contained in:
Daniel Gultsch 2021-05-04 19:04:01 +02:00
parent 9544b994dc
commit e2324209ed
3 changed files with 46 additions and 9 deletions

View file

@ -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);
}
}
}

View file

@ -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);
}

View file

@ -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;
}
}