Add commentary

This commit is contained in:
Paul Schaub 2018-06-09 20:12:05 +02:00
parent 120793a6f5
commit 015c49d356
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
1 changed files with 95 additions and 23 deletions

View File

@ -56,18 +56,19 @@ import org.whispersystems.libsignal.IdentityKey;
/** /**
* Test * Command Line OMEMO Chat Client.
* This client was developed for testing purposes. It can easily crash for unexpected inputs. Use with that in mind.
*
* Created by vanitas on 28.11.16. * Created by vanitas on 28.11.16.
*/ */
public class Main { public class Main {
private AbstractXMPPConnection connection; private AbstractXMPPConnection connection;
private OmemoManager omemoManager; private OmemoManager omemoManager;
private OmemoManager.LoggedInOmemoManager managerGuard;
private final static File storePath = new File("store"); private final static File storePath = new File("store");
private Main() throws XmppStringprepException { private Main() {
//* /*
SmackConfiguration.DEBUG = true; SmackConfiguration.DEBUG = true;
/*/ /*/
SmackConfiguration.DEBUG = false; SmackConfiguration.DEBUG = false;
@ -124,7 +125,6 @@ public class Main {
connection = connection.connect(); connection = connection.connect();
connection.login(); connection.login();
omemoManager.initialize(); 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...");
@ -165,14 +165,17 @@ public class Main {
} }
}; };
// Carbon Copies
CarbonManager.getInstanceFor(connection).enableCarbons(); CarbonManager.getInstanceFor(connection).enableCarbons();
omemoManager.addOmemoMessageListener(messageListener); omemoManager.addOmemoMessageListener(messageListener);
omemoManager.addOmemoMucMessageListener(mucMessageListener); omemoManager.addOmemoMucMessageListener(mucMessageListener);
// Contact list
Roster roster = Roster.getInstanceFor(connection); Roster roster = Roster.getInstanceFor(connection);
roster.setSubscriptionMode(Roster.SubscriptionMode.accept_all); roster.setSubscriptionMode(Roster.SubscriptionMode.accept_all);
// Single Chats
ChatManager cm = ChatManager.getInstanceFor(connection); ChatManager cm = ChatManager.getInstanceFor(connection);
cm.addChatListener((chat, b) -> chat.addMessageListener((chat1, message) -> { cm.addChatListener((chat, b) -> chat.addMessageListener((chat1, message) -> {
if(message.getBody() != null && chat1 != null) { if(message.getBody() != null && chat1 != null) {
@ -180,6 +183,7 @@ public class Main {
} }
})); }));
// Group Chats
MultiUserChatManager mucm = MultiUserChatManager.getInstanceFor(connection); MultiUserChatManager mucm = MultiUserChatManager.getInstanceFor(connection);
mucm.setAutoJoinOnReconnect(true); mucm.setAutoJoinOnReconnect(true);
mucm.addInvitationListener((xmppConnection, multiUserChat, entityFullJid, s, s1, message, invite) -> { mucm.addInvitationListener((xmppConnection, multiUserChat, entityFullJid, s, s1, message, invite) -> {
@ -197,6 +201,7 @@ public class Main {
Chat current = null; Chat current = null;
boolean omemo = false; boolean omemo = false;
// Begin REPL
while (true) { while (true) {
String line = null; String line = null;
try { try {
@ -207,6 +212,8 @@ public class Main {
return; return;
} }
String [] split = line.split(" "); String [] split = line.split(" ");
// Send unencrypted chat message
if(line.startsWith("/chat ")) { if(line.startsWith("/chat ")) {
String l = line.substring("/chat ".length()); String l = line.substring("/chat ".length());
if(l.length() == 0) { if(l.length() == 0) {
@ -219,11 +226,17 @@ public class Main {
current.sendMessage(l.substring(id.length() + 1)); current.sendMessage(l.substring(id.length() + 1));
} }
} }
} else if (line.startsWith("/quit")) { }
// Exit the client
else if (line.startsWith("/quit")) {
scanner.close(); scanner.close();
connection.disconnect(new Presence(Presence.Type.unavailable, "Smack is still alive :D", 100, Presence.Mode.away)); connection.disconnect(new Presence(Presence.Type.unavailable, "Smack is still alive :D", 100, Presence.Mode.away));
break; break;
} else if (line.startsWith("/add")) { }
// Add contacts
else if (line.startsWith("/add")) {
String jid = split.length == 4 ? split[1] : null; String jid = split.length == 4 ? split[1] : null;
if(jid != null) { if(jid != null) {
BareJid b = JidCreate.bareFrom(jid); BareJid b = JidCreate.bareFrom(jid);
@ -231,13 +244,19 @@ public class Main {
} else { } else {
System.out.println("Usage: /add jid@server nick group"); System.out.println("Usage: /add jid@server nick group");
} }
} else if(line.startsWith("/remove")) { }
// Remove contact
else if(line.startsWith("/remove")) {
if(split.length == 2) { if(split.length == 2) {
BareJid b = getJid(split[1]); BareJid b = getJid(split[1]);
roster.removeEntry(roster.getEntry(b)); roster.removeEntry(roster.getEntry(b));
System.out.println("Removed contact from roster"); System.out.println("Removed contact from roster");
} }
} else if(line.startsWith("/list")){ }
// List available contacts/groups or device list of selected contact
else if(line.startsWith("/list")){
if(split.length == 1) { if(split.length == 1) {
for (RosterEntry r : roster.getEntries()) { for (RosterEntry r : roster.getEntries()) {
@ -246,7 +265,10 @@ public class Main {
for (EntityBareJid r : mucm.getJoinedRooms()) { for (EntityBareJid r : mucm.getJoinedRooms()) {
System.out.println(r.asBareJid().toString()); System.out.println(r.asBareJid().toString());
} }
} else { }
// List presences of one contact, as well as OMEMO fingerprints
else {
BareJid jid = getJid(split[1]); BareJid jid = getJid(split[1]);
try { try {
List<Presence> presences = roster.getAllPresences(jid); List<Presence> presences = roster.getAllPresences(jid);
@ -276,7 +298,10 @@ public class Main {
System.out.println(i+": "+fps.get(i)); System.out.println(i+": "+fps.get(i));
} }
} }
} else if(line.startsWith("/trust")) { }
// Make trust decisions for keys of a user
else if(line.startsWith("/trust")) {
if(split.length == 2) { if(split.length == 2) {
System.out.println("Usage: \n0: Untrusted, 1: Trusted, otherwise: Undecided"); System.out.println("Usage: \n0: Untrusted, 1: Trusted, otherwise: Undecided");
BareJid jid = getJid(split[1]); BareJid jid = getJid(split[1]);
@ -315,13 +340,19 @@ public class Main {
} }
} }
} else if(line.startsWith("/purge")) { }
// Delete foreign OMEMO devices from own device list
else if(line.startsWith("/purge")) {
omemoManager.purgeDeviceList(); omemoManager.purgeDeviceList();
System.out.println("Purge successful."); System.out.println("Purge successful.");
// } else if(line.startsWith("/regenerate")) { // } else if(line.startsWith("/regenerate")) {
// omemoManager.regenerateIdentity(); // omemoManager.regenerateIdentity();
// System.out.println("Regeneration successful."); // System.out.println("Regeneration successful.");
} else if(line.startsWith("/omemo")) { }
// Write encrypted OMEMO message to single chat
else if(line.startsWith("/omemo")) {
if(split.length == 1) { if(split.length == 1) {
} else { } else {
BareJid recipient = getJid(split[1]); BareJid recipient = getJid(split[1]);
@ -349,6 +380,8 @@ public class Main {
} }
omemo = true; omemo = true;
} }
// Send encrypted OMEMO message to group chat
else if(line.startsWith("/mucomemo")) { else if(line.startsWith("/mucomemo")) {
if(split.length >= 3) { if(split.length >= 3) {
BareJid mucJid = getJid(split[1]); BareJid mucJid = getJid(split[1]);
@ -375,10 +408,16 @@ public class Main {
} }
} }
} }
} else if(line.startsWith("/fingerprint")) { }
// Display own fingerprint
else if(line.startsWith("/fingerprint")) {
OmemoFingerprint fingerprint = omemoManager.getOwnFingerprint(); OmemoFingerprint fingerprint = omemoManager.getOwnFingerprint();
System.out.println(fingerprint.blocksOf8Chars()); System.out.println(fingerprint.blocksOf8Chars());
} else if(line.startsWith("/help")) { }
// Display help text
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" +
"/chat <Nickname/Jid> <Message>: Send a normal unencrypted chat message to a user. \n" + "/chat <Nickname/Jid> <Message>: Send a normal unencrypted chat message to a user. \n" +
@ -400,7 +439,10 @@ public class Main {
// 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")) { }
// Send ratchet update message to repair/forward session with contact
else if(line.startsWith("/ratchetUpdate")) {
if(split.length == 2) { if(split.length == 2) {
BareJid jid = getJid(split[1]); BareJid jid = getJid(split[1]);
OmemoCachedDeviceList cachedDeviceList = service.getOmemoStoreBackend().loadCachedDeviceList(omemoManager.getOwnDevice(), jid); OmemoCachedDeviceList cachedDeviceList = service.getOmemoStoreBackend().loadCachedDeviceList(omemoManager.getOwnDevice(), jid);
@ -410,6 +452,8 @@ public class Main {
} }
} }
} }
// If no command is entered, assume chat with contact is still active -> send message
else { else {
if(current != null) { if(current != null) {
if(!omemo) { if(!omemo) {
@ -427,13 +471,11 @@ public class Main {
} }
} }
} }
} } else {
else
System.out.println("please open a chat"); System.out.println("please open a chat");
}
} }
} }
} }
public static void main(String[] args) { public static void main(String[] args) {
@ -445,7 +487,13 @@ public class Main {
} }
} }
public BareJid getJid(String user) { /**
* Translate Nick to JID.
*
* @param user Nick or Jid of a contact as String
* @return BareJid of the contact or null, if jid cannot be determined.
*/
private BareJid getJid(String user) {
Roster roster = Roster.getInstanceFor(connection); Roster roster = Roster.getInstanceFor(connection);
RosterEntry r = null; RosterEntry r = null;
for(RosterEntry s : roster.getEntries()) { for(RosterEntry s : roster.getEntries()) {
@ -466,7 +514,18 @@ public class Main {
} }
} }
public void storeTrust(OmemoDevice userDevice, OmemoDevice contactsDevice, OmemoFingerprint fingerprint, TrustState trustState) /**
* Store a trust decision in persistent storage.
* This particular method mimics the behaviour of the {@link SignalFileBasedOmemoStore}.
*
* @param userDevice our own OMEMO device
* @param contactsDevice OMEMO device of the contact in question
* @param fingerprint the contacts devices fingerprint
* @param trustState the new trust state.
*
* @throws IOException IO is dangerous (we write to a file)
*/
private void storeTrust(OmemoDevice userDevice, OmemoDevice contactsDevice, OmemoFingerprint fingerprint, TrustState trustState)
throws IOException { throws IOException {
File target = new File(storePath, "OMEMO_Store" + File.separator + File target = new File(storePath, "OMEMO_Store" + File.separator +
userDevice.getJid().toString() + File.separator + userDevice.getJid().toString() + File.separator +
@ -487,7 +546,20 @@ public class Main {
} }
} }
public TrustState getTrust(OmemoDevice userDevice, OmemoDevice contactsDevice, OmemoFingerprint fingerprint) /**
* Retrieves a trust decision from persistent storage.
* If no trust record was found, return undecided.
* If a trust record for that device with a different fingerprint was found, return untrusted.
* This particular method mimics the behaviour of the {@link SignalFileBasedOmemoStore}.
*
* @param userDevice our own OMEMO device
* @param contactsDevice OMEMO device of the contact in question
* @param fingerprint contacts devices fingerprint.
* @return trust state
*
* @throws IOException IO is dangerous (we read from a file)
*/
private TrustState getTrust(OmemoDevice userDevice, OmemoDevice contactsDevice, OmemoFingerprint fingerprint)
throws IOException { throws IOException {
File target = new File(storePath, "OMEMO_Store" + File.separator + File target = new File(storePath, "OMEMO_Store" + File.separator +
userDevice.getJid().toString() + File.separator + userDevice.getJid().toString() + File.separator +