This commit is contained in:
Paul Schaub 2018-01-17 14:36:03 +01:00
parent 9890dd4863
commit 623624ee17
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
5 changed files with 95 additions and 94 deletions

View file

@ -11,7 +11,7 @@ repositories {
} }
ext { ext {
smackVersion="4.2.1-SNAPSHOT" smackVersion="4.2.3-SNAPSHOT"
} }
dependencies { dependencies {

View file

@ -1,6 +1,6 @@
#Sun Apr 23 19:00:03 CEST 2017 #Tue Oct 24 19:06:03 CEST 2017
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.13-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-2.13-all.zip

BIN
received Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 KiB

BIN
sending Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

View file

@ -1,6 +1,5 @@
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Scanner; import java.util.Scanner;
@ -12,31 +11,29 @@ import org.jivesoftware.smack.chat.Chat;
import org.jivesoftware.smack.chat.ChatManager; import org.jivesoftware.smack.chat.ChatManager;
import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Presence; import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smack.roster.Roster; import org.jivesoftware.smack.roster.Roster;
import org.jivesoftware.smack.roster.RosterEntry; import org.jivesoftware.smack.roster.RosterEntry;
import org.jivesoftware.smack.tcp.XMPPTCPConnection; import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smackx.carbons.CarbonManager; import org.jivesoftware.smackx.carbons.CarbonManager;
import org.jivesoftware.smackx.mam.MamManager; import org.jivesoftware.smackx.carbons.packet.CarbonExtension;
import org.jivesoftware.smackx.muc.MultiUserChat; import org.jivesoftware.smackx.muc.MultiUserChat;
import org.jivesoftware.smackx.muc.MultiUserChatException; import org.jivesoftware.smackx.muc.MultiUserChatException;
import org.jivesoftware.smackx.muc.MultiUserChatManager; import org.jivesoftware.smackx.muc.MultiUserChatManager;
import org.jivesoftware.smackx.omemo.OmemoConfiguration; import org.jivesoftware.smackx.omemo.OmemoConfiguration;
import org.jivesoftware.smackx.omemo.OmemoFingerprint;
import org.jivesoftware.smackx.omemo.OmemoManager; import org.jivesoftware.smackx.omemo.OmemoManager;
import org.jivesoftware.smackx.omemo.OmemoService; import org.jivesoftware.smackx.omemo.OmemoMessage;
import org.jivesoftware.smackx.omemo.exceptions.CannotEstablishOmemoSessionException;
import org.jivesoftware.smackx.omemo.exceptions.UndecidedOmemoIdentityException; import org.jivesoftware.smackx.omemo.exceptions.UndecidedOmemoIdentityException;
import org.jivesoftware.smackx.omemo.internal.CachedDeviceList; import org.jivesoftware.smackx.omemo.internal.OmemoCachedDeviceList;
import org.jivesoftware.smackx.omemo.internal.CipherAndAuthTag;
import org.jivesoftware.smackx.omemo.internal.ClearTextMessage;
import org.jivesoftware.smackx.omemo.internal.OmemoDevice; import org.jivesoftware.smackx.omemo.internal.OmemoDevice;
import org.jivesoftware.smackx.omemo.internal.OmemoMessageInformation;
import org.jivesoftware.smackx.omemo.listener.OmemoMessageListener; import org.jivesoftware.smackx.omemo.listener.OmemoMessageListener;
import org.jivesoftware.smackx.omemo.listener.OmemoMucMessageListener; import org.jivesoftware.smackx.omemo.listener.OmemoMucMessageListener;
import org.jivesoftware.smackx.omemo.signal.SignalCachingOmemoStore;
import org.jivesoftware.smackx.omemo.signal.SignalFileBasedOmemoStore; import org.jivesoftware.smackx.omemo.signal.SignalFileBasedOmemoStore;
import org.jivesoftware.smackx.omemo.signal.SignalOmemoService; import org.jivesoftware.smackx.omemo.signal.SignalOmemoService;
import org.jivesoftware.smackx.omemo.signal.SignalOmemoSession; import org.jivesoftware.smackx.omemo.trust.OmemoFingerprint;
import org.jivesoftware.smackx.omemo.util.OmemoKeyUtil; import org.jivesoftware.smackx.omemo.trust.OmemoTrustCallback;
import org.jivesoftware.smackx.omemo.trust.TrustState;
import org.jline.reader.EndOfFileException; import org.jline.reader.EndOfFileException;
import org.jline.reader.LineReader; import org.jline.reader.LineReader;
@ -59,6 +56,7 @@ import org.whispersystems.libsignal.IdentityKey;
public class Main { public class Main {
private AbstractXMPPConnection connection; private AbstractXMPPConnection connection;
private OmemoManager omemoManager; private OmemoManager omemoManager;
private OmemoManager.LoggedInOmemoManager managerGuard;
private Main() throws XmppStringprepException { private Main() throws XmppStringprepException {
//* //*
@ -90,22 +88,40 @@ public class Main {
SignalOmemoService.acknowledgeLicense(); SignalOmemoService.acknowledgeLicense();
SignalOmemoService.setup(); SignalOmemoService.setup();
OmemoConfiguration.setFileBasedOmemoStoreDefaultPath(new File("store")); SignalOmemoService service = (SignalOmemoService) SignalOmemoService.getInstance();
service.setOmemoStoreBackend(new SignalCachingOmemoStore(new SignalFileBasedOmemoStore(new File("store"))));
omemoManager = OmemoManager.getInstanceFor(connection); omemoManager = OmemoManager.getInstanceFor(connection);
SignalFileBasedOmemoStore omemoStore = (SignalFileBasedOmemoStore) OmemoService.getInstance().getOmemoStoreBackend(); omemoManager.setTrustCallback(new OmemoTrustCallback() {
@Override
public TrustState getTrust(OmemoDevice device, OmemoFingerprint fingerprint) {
return TrustState.trusted;
}
@Override
public void setTrust(OmemoDevice device, OmemoFingerprint fingerprint, TrustState state) {
}
});
connection.setPacketReplyTimeout(10000); connection.setPacketReplyTimeout(10000);
connection = connection.connect(); connection = connection.connect();
connection.login(); connection.login();
omemoManager.initialize();
managerGuard = new OmemoManager.LoggedInOmemoManager(omemoManager);
System.out.println("Logged in. Begin setting up OMEMO..."); System.out.println("Logged in. Begin setting up OMEMO...");
OmemoMessageListener messageListener = new OmemoMessageListener() { OmemoMessageListener messageListener = new OmemoMessageListener() {
@Override @Override
public void onOmemoMessageReceived(String decryptedBody, Message encryptedMessage, Message wrappingMessage, OmemoMessageInformation omemoInformation) { public void onOmemoMessageReceived(Stanza stanza, OmemoMessage.Received received) {
BareJid sender = encryptedMessage.getFrom().asBareJid(); BareJid sender = stanza.getFrom().asBareJid();
if (received.isKeyTransportMessage()) {
return;
}
String decryptedBody = received.getBody();
if (sender != null && decryptedBody != null) { if (sender != null && decryptedBody != null) {
reader.callWidget(LineReader.CLEAR); reader.callWidget(LineReader.CLEAR);
reader.getTerminal().writer().println("\033[34m" + sender + ": " + decryptedBody + "\033[0m "+(omemoInformation != null ? omemoInformation : "")); reader.getTerminal().writer().println("\033[34m" + sender + ": " + decryptedBody);
reader.callWidget(LineReader.REDRAW_LINE); reader.callWidget(LineReader.REDRAW_LINE);
reader.callWidget(LineReader.REDISPLAY); reader.callWidget(LineReader.REDISPLAY);
reader.getTerminal().writer().flush(); reader.getTerminal().writer().flush();
@ -113,30 +129,19 @@ public class Main {
} }
@Override @Override
public void onOmemoKeyTransportReceived(CipherAndAuthTag cipherAndAuthTag, Message message, Message wrappingMessage, OmemoMessageInformation omemoInformation) { public void onOmemoCarbonCopyReceived(CarbonExtension.Direction direction, Message carbonCopy, Message wrappingMessage, OmemoMessage.Received decryptedCarbonCopy) {
reader.callWidget(LineReader.CLEAR);
reader.getTerminal().writer().println("KeyTransportElement received from "+message.getFrom());
reader.callWidget(LineReader.REDRAW_LINE);
reader.callWidget(LineReader.REDISPLAY);
reader.getTerminal().writer().flush();
} }
}; };
OmemoMucMessageListener mucMessageListener = new OmemoMucMessageListener() { OmemoMucMessageListener mucMessageListener = (multiUserChat, stanza, received) -> {
@Override BareJid bareJid = received.getSenderDevice().getJid();
public void onOmemoMucMessageReceived(MultiUserChat multiUserChat, BareJid bareJid, String s, Message message, Message message1, OmemoMessageInformation omemoMessageInformation) { if (received.isKeyTransportMessage()) {
return;
}
String s = received.getBody();
if (multiUserChat != null && bareJid != null && s != null) { if (multiUserChat != null && bareJid != null && s != null) {
reader.callWidget(LineReader.CLEAR); reader.callWidget(LineReader.CLEAR);
reader.getTerminal().writer().println("\033[36m" + multiUserChat.getRoom() + ": " + bareJid + ": " + s + "\033[0m " + (omemoMessageInformation != null ? omemoMessageInformation : "")); reader.getTerminal().writer().println("\033[36m" + multiUserChat.getRoom() + ": " + bareJid + ": " + s);
reader.callWidget(LineReader.REDRAW_LINE);
reader.callWidget(LineReader.REDISPLAY);
reader.getTerminal().writer().flush();
}
}
@Override
public void onOmemoKeyTransportReceived(MultiUserChat muc, BareJid from, CipherAndAuthTag cipherAndAuthTag, Message message, Message wrappingMessage, OmemoMessageInformation omemoInformation) {
reader.callWidget(LineReader.CLEAR);
reader.getTerminal().writer().println("KeyTransportElement received from "+muc.getRoom().asBareJid()+"/"+from);
reader.callWidget(LineReader.REDRAW_LINE); reader.callWidget(LineReader.REDRAW_LINE);
reader.callWidget(LineReader.REDISPLAY); reader.callWidget(LineReader.REDISPLAY);
reader.getTerminal().writer().flush(); reader.getTerminal().writer().flush();
@ -229,23 +234,25 @@ public class Main {
try { try {
List<Presence> presences = roster.getAllPresences(jid); List<Presence> presences = roster.getAllPresences(jid);
for(Presence p : presences) { for(Presence p : presences) {
System.out.println(p.getFrom()+" "+omemoManager.resourceSupportsOmemo(p.getFrom().asDomainFullJidIfPossible())); System.out.println(p.getFrom());
} }
} catch (Exception e) {} } catch (Exception e) {}
omemoManager.requestDeviceListUpdateFor(jid); omemoManager.requestDeviceListUpdateFor(jid);
omemoManager.buildSessionsWith(jid); OmemoCachedDeviceList list = service.getOmemoStoreBackend().loadCachedDeviceList(omemoManager.getOwnDevice(), jid);
CachedDeviceList list = omemoStore.loadCachedDeviceList(omemoManager, jid);
if(list == null) { if(list == null) {
list = new CachedDeviceList(); list = new OmemoCachedDeviceList();
} }
ArrayList<String> fps = new ArrayList<>(); ArrayList<String> fps = new ArrayList<>();
for(int id : list.getActiveDevices()) { for(int id : list.getActiveDevices()) {
OmemoDevice d = new OmemoDevice(jid, id); OmemoDevice d = new OmemoDevice(jid, id);
IdentityKey idk = omemoStore.loadOmemoIdentityKey(omemoManager, d); IdentityKey idk = service.getOmemoStoreBackend().loadOmemoIdentityKey(omemoManager.getOwnDevice(), d);
if(idk == null) { if(idk == null) {
System.out.println("No identityKey for "+d); System.out.println("No identityKey for "+d);
} else { } else {
fps.add(OmemoKeyUtil.prettyFingerprint(omemoStore.keyUtil().getFingerprint(idk))); OmemoFingerprint fp = service.getOmemoStoreBackend().getFingerprint(omemoManager.getOwnDevice(), d);
if (fp != null) {
fps.add(fp.blocksOf8Chars());
}
} }
} }
for(int i=0; i<fps.size(); i++) { for(int i=0; i<fps.size(); i++) {
@ -261,25 +268,16 @@ public class Main {
continue; continue;
} }
omemoManager.requestDeviceListUpdateFor(jid); System.out.println(jid);
CachedDeviceList l = omemoStore.loadCachedDeviceList(omemoManager, jid);
l.getActiveDevices().stream().filter(i -> (!jid.equals(connection.getUser().asBareJid()) || i != omemoManager.getDeviceId())).forEach(i -> { omemoManager.requestDeviceListUpdateFor(jid);
OmemoDevice d = new OmemoDevice(jid, i);
SignalOmemoSession s = (SignalOmemoSession) omemoStore.getOmemoSessionOf(omemoManager, d);
if(s.getIdentityKey() == null) { for (OmemoDevice device : omemoManager.getDevicesOf(jid)) {
try { OmemoFingerprint fp = omemoManager.getFingerprint(device);
System.out.println("Build session...");
omemoManager.getFingerprint(d); if (omemoManager.isDecidedOmemoIdentity(device, fp)) {
s = (SignalOmemoSession) omemoStore.getOmemoSessionOf(omemoManager, d); if (omemoManager.isTrustedOmemoIdentity(device, fp)) {
System.out.println("Session built.");
} catch (CannotEstablishOmemoSessionException e) {
e.printStackTrace();
return;
}
}
if (omemoStore.isDecidedOmemoIdentity(omemoManager, d, s.getIdentityKey())) {
if (omemoStore.isTrustedOmemoIdentity(omemoManager, d, s.getIdentityKey())) {
System.out.println("Status: Trusted"); System.out.println("Status: Trusted");
} else { } else {
System.out.println("Status: Untrusted"); System.out.println("Status: Untrusted");
@ -287,24 +285,25 @@ public class Main {
} else { } else {
System.out.println("Status: Undecided"); System.out.println("Status: Undecided");
} }
System.out.println(OmemoKeyUtil.prettyFingerprint(s.getFingerprint()));
System.out.println(fp.blocksOf8Chars());
String decision = scanner.nextLine(); String decision = scanner.nextLine();
if (decision.equals("0")) { if (decision.equals("0")) {
omemoStore.distrustOmemoIdentity(omemoManager, d, s.getIdentityKey()); omemoManager.distrustOmemoIdentity(device, fp);
System.out.println("Identity has been untrusted."); System.out.println("Identity has been untrusted.");
} else if (decision.equals("1")) { } else if (decision.equals("1")) {
omemoStore.trustOmemoIdentity(omemoManager, d, s.getIdentityKey()); omemoManager.trustOmemoIdentity(device, fp);
System.out.println("Identity has been trusted."); System.out.println("Identity has been trusted.");
} }
}); }
} }
} else if(line.startsWith("/purge")) { } else if(line.startsWith("/purge")) {
omemoManager.purgeDevices(); omemoManager.purgeDeviceList();
System.out.println("Purge successful."); System.out.println("Purge successful.");
} else if(line.startsWith("/regenerate")) { // } else if(line.startsWith("/regenerate")) {
omemoManager.regenerate(); // omemoManager.regenerateIdentity();
System.out.println("Regeneration successful."); // System.out.println("Regeneration successful.");
} else if(line.startsWith("/omemo")) { } else if(line.startsWith("/omemo")) {
if(split.length == 1) { if(split.length == 1) {
} else { } else {
@ -314,20 +313,20 @@ public class Main {
for (int i = 2; i < split.length; i++) { for (int i = 2; i < split.length; i++) {
message += split[i] + " "; message += split[i] + " ";
} }
Message encrypted = null; OmemoMessage.Sent encrypted = null;
try { try {
encrypted = omemoManager.encrypt(recipient, message.trim()); encrypted = omemoManager.encrypt(recipient, message.trim());
} catch (UndecidedOmemoIdentityException e) { } catch (UndecidedOmemoIdentityException e) {
System.out.println("There are undecided identities:"); System.out.println("There are undecided identities:");
for(OmemoDevice d : e.getUntrustedDevices()) { for(OmemoDevice d : e.getUndecidedDevices()) {
System.out.println(d.toString()); System.out.println(d.toString());
} }
} catch (CannotEstablishOmemoSessionException e) {
encrypted = omemoManager.encryptForExistingSessions(e, message);
} }
if(encrypted != null) { if(encrypted != null) {
current = cm.createChat(recipient.asEntityJidIfPossible()); current = cm.createChat(recipient.asEntityJidIfPossible());
current.sendMessage(encrypted); Message m = new Message();
m.addExtension(encrypted.getElement());
current.sendMessage(m);
} }
} }
} }
@ -342,26 +341,26 @@ public class Main {
message += split[i] + " "; message += split[i] + " ";
} }
MultiUserChat muc = mucm.getMultiUserChat(mucJid.asEntityBareJidIfPossible()); MultiUserChat muc = mucm.getMultiUserChat(mucJid.asEntityBareJidIfPossible());
Message encrypted = null; OmemoMessage.Sent encrypted = null;
try { try {
encrypted = omemoManager.encrypt(muc, message.trim()); encrypted = omemoManager.encrypt(muc, message.trim());
} catch (UndecidedOmemoIdentityException e) { } catch (UndecidedOmemoIdentityException e) {
System.out.println("There are undecided identities:"); System.out.println("There are undecided identities:");
for(OmemoDevice d : e.getUntrustedDevices()) { for(OmemoDevice d : e.getUndecidedDevices()) {
System.out.println(d.toString()); System.out.println(d.toString());
} }
} catch (CannotEstablishOmemoSessionException e) {
encrypted = omemoManager.encryptForExistingSessions(e, message);
} }
if(encrypted != null) { if(encrypted != null) {
muc.sendMessage(encrypted); Message m = new Message();
m.addExtension(encrypted.getElement());
muc.sendMessage(m);
} }
} }
} }
} else if(line.startsWith("/fingerprint")) { } else if(line.startsWith("/fingerprint")) {
OmemoFingerprint fingerprint = omemoManager.getOurFingerprint(); OmemoFingerprint fingerprint = omemoManager.getOwnFingerprint();
System.out.println(OmemoKeyUtil.prettyFingerprint(fingerprint)); System.out.println(fingerprint.blocksOf8Chars());
} else if(line.startsWith("/help")) { } else if(line.startsWith("/help")) {
if(split.length == 1) { if(split.length == 1) {
System.out.println("Available options: \n" + System.out.println("Available options: \n" +
@ -377,17 +376,17 @@ public class Main {
"/remove <jid>: Remove a contact from your roster. \n" + "/remove <jid>: Remove a contact from your roster. \n" +
"/quit: Quit the application."); "/quit: Quit the application.");
} }
} else if(line.startsWith("/mam")) { // } else if(line.startsWith("/mam")) {
MamManager mamManager = MamManager.getInstanceFor(connection); // MamManager mamManager = MamManager.getInstanceFor(connection);
MamManager.MamQueryResult result = mamManager.queryArchive(new Date(System.currentTimeMillis()-1000*60*60*24), new Date(System.currentTimeMillis())); // MamManager.MamQueryResult result = mamManager.queryArchive(new Date(System.currentTimeMillis()-1000*60*60*24), new Date(System.currentTimeMillis()));
for(ClearTextMessage d : omemoManager.decryptMamQueryResult(result)) { // for(ClearTextMessage d : omemoManager.decryptMamQueryResult(result)) {
messageListener.onOmemoMessageReceived(d.getBody(), d.getOriginalMessage(), null, d.getMessageInformation()); // messageListener.onOmemoMessageReceived(d.getBody(), d.getOriginalMessage(), null, d.getMessageInformation());
} // }
System.out.println("Query finished"); // System.out.println("Query finished");
} else if(line.startsWith("/ratchetUpdate")) { } else if(line.startsWith("/ratchetUpdate")) {
if(split.length == 2) { if(split.length == 2) {
BareJid jid = getJid(split[1]); BareJid jid = getJid(split[1]);
CachedDeviceList cachedDeviceList = omemoStore.loadCachedDeviceList(omemoManager, jid); OmemoCachedDeviceList cachedDeviceList = service.getOmemoStoreBackend().loadCachedDeviceList(omemoManager.getOwnDevice(), jid);
for(int id : cachedDeviceList.getActiveDevices()) { for(int id : cachedDeviceList.getActiveDevices()) {
OmemoDevice d = new OmemoDevice(jid, id); OmemoDevice d = new OmemoDevice(jid, id);
omemoManager.sendRatchetUpdateMessage(d); omemoManager.sendRatchetUpdateMessage(d);
@ -400,11 +399,13 @@ public class Main {
current.sendMessage(line); current.sendMessage(line);
} else { } else {
try { try {
Message e = omemoManager.encrypt(current.getParticipant().asEntityBareJid(), line.trim()); OmemoMessage.Sent e = omemoManager.encrypt(current.getParticipant().asEntityBareJid(), line.trim());
current.sendMessage(e); Message m = new Message();
m.addExtension(e.getElement());
current.sendMessage(m);
} catch (UndecidedOmemoIdentityException e) { } catch (UndecidedOmemoIdentityException e) {
System.out.println("There are undecided identities:"); System.out.println("There are undecided identities:");
for(OmemoDevice d : e.getUntrustedDevices()) { for(OmemoDevice d : e.getUndecidedDevices()) {
System.out.println(d.toString()); System.out.println(d.toString());
} }
} }