diff --git a/briar-android/src/net/sf/briar/android/invitation/AddContactActivity.java b/briar-android/src/net/sf/briar/android/invitation/AddContactActivity.java index 14798d6255b02578d4b9a48c4796301b3b9eb1ba..6c22e433c56d3a8665612bf1b4469d1a696e4a64 100644 --- a/briar-android/src/net/sf/briar/android/invitation/AddContactActivity.java +++ b/briar-android/src/net/sf/briar/android/invitation/AddContactActivity.java @@ -288,9 +288,11 @@ implements InvitationListener { if(code == remoteConfirmationCode) { localMatched = true; if(remoteMatched) setView(new ContactDetailsView(this)); + else if(remoteCompared) setView(new CodesDoNotMatchView(this)); else setView(new WaitForContactView(this)); task.localConfirmationSucceeded(); } else { + localMatched = false; setView(new CodesDoNotMatchView(this)); task.localConfirmationFailed(); } @@ -353,6 +355,7 @@ implements InvitationListener { runOnUiThread(new Runnable() { public void run() { remoteCompared = true; + remoteMatched = false; if(localMatched) setView(new CodesDoNotMatchView(AddContactActivity.this)); } diff --git a/briar-core/src/net/sf/briar/invitation/AliceConnector.java b/briar-core/src/net/sf/briar/invitation/AliceConnector.java index 580195cd1c070109050c6604d6d62fb6368f3a66..6337959617ce595c273f8c6820903f9f55583c08 100644 --- a/briar-core/src/net/sf/briar/invitation/AliceConnector.java +++ b/briar-core/src/net/sf/briar/invitation/AliceConnector.java @@ -106,23 +106,30 @@ class AliceConnector extends Connector { int aliceCode = codes[0], bobCode = codes[1]; group.keyAgreementSucceeded(aliceCode, bobCode); // Exchange confirmation results + boolean localMatched, remoteMatched; try { - sendConfirmation(w); - if(receiveConfirmation(r)) group.remoteConfirmationSucceeded(); - else group.remoteConfirmationFailed(); + localMatched = group.waitForLocalConfirmationResult(); + sendConfirmation(w, localMatched); + remoteMatched = receiveConfirmation(r); } catch(IOException e) { if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); - tryToClose(conn, true); group.remoteConfirmationFailed(); + tryToClose(conn, true); return; } catch(InterruptedException e) { if(LOG.isLoggable(WARNING)) LOG.warning("Interrupted while waiting for confirmation"); - tryToClose(conn, true); group.remoteConfirmationFailed(); + tryToClose(conn, true); Thread.currentThread().interrupt(); return; } + if(remoteMatched) group.remoteConfirmationSucceeded(); + else group.remoteConfirmationFailed(); + if(!(localMatched && remoteMatched)) { + tryToClose(conn, false); + return; + } // The timestamp is taken after exhanging confirmation results long localTimestamp = clock.currentTimeMillis(); // Confirmation succeeded - upgrade to a secure connection @@ -152,13 +159,13 @@ class AliceConnector extends Connector { remoteProps = receiveTransportProperties(r); } catch(GeneralSecurityException e) { if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); - tryToClose(conn, true); group.pseudonymExchangeFailed(); + tryToClose(conn, true); return; } catch(IOException e) { if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); - tryToClose(conn, true); group.pseudonymExchangeFailed(); + tryToClose(conn, true); return; } // The epoch is the minimum of the peers' timestamps diff --git a/briar-core/src/net/sf/briar/invitation/BobConnector.java b/briar-core/src/net/sf/briar/invitation/BobConnector.java index 8d7d2ad09f58f23e4a69aec280d8dc622a27082b..3f03a65b618b135b6abc34df248cb03615d50124 100644 --- a/briar-core/src/net/sf/briar/invitation/BobConnector.java +++ b/briar-core/src/net/sf/briar/invitation/BobConnector.java @@ -106,23 +106,30 @@ class BobConnector extends Connector { int aliceCode = codes[0], bobCode = codes[1]; group.keyAgreementSucceeded(bobCode, aliceCode); // Exchange confirmation results + boolean localMatched, remoteMatched; try { - if(receiveConfirmation(r)) group.remoteConfirmationSucceeded(); - else group.remoteConfirmationFailed(); - sendConfirmation(w); + remoteMatched = receiveConfirmation(r); + localMatched = group.waitForLocalConfirmationResult(); + sendConfirmation(w, localMatched); } catch(IOException e) { if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); - tryToClose(conn, true); group.remoteConfirmationFailed(); + tryToClose(conn, true); return; } catch(InterruptedException e) { if(LOG.isLoggable(WARNING)) LOG.warning("Interrupted while waiting for confirmation"); - tryToClose(conn, true); group.remoteConfirmationFailed(); + tryToClose(conn, true); Thread.currentThread().interrupt(); return; } + if(remoteMatched) group.remoteConfirmationSucceeded(); + else group.remoteConfirmationFailed(); + if(!(localMatched && remoteMatched)) { + tryToClose(conn, false); + return; + } // The timestamp is taken after exhanging confirmation results long localTimestamp = clock.currentTimeMillis(); // Confirmation succeeded - upgrade to a secure connection @@ -152,13 +159,13 @@ class BobConnector extends Connector { sendTransportProperties(w); } catch(GeneralSecurityException e) { if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); - tryToClose(conn, true); group.pseudonymExchangeFailed(); + tryToClose(conn, true); return; } catch(IOException e) { if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); - tryToClose(conn, true); group.pseudonymExchangeFailed(); + tryToClose(conn, true); return; } // The epoch is the minimum of the peers' timestamps diff --git a/briar-core/src/net/sf/briar/invitation/Connector.java b/briar-core/src/net/sf/briar/invitation/Connector.java index c58d9d4b3c4968389c3781c7fba831cb1876b949..f0fd6b09559b8658e8d3303a7dfc057df730aa21 100644 --- a/briar-core/src/net/sf/briar/invitation/Connector.java +++ b/briar-core/src/net/sf/briar/invitation/Connector.java @@ -175,21 +175,23 @@ abstract class Connector extends Thread { throw new GeneralSecurityException(); } // Derive the master secret + if(LOG.isLoggable(INFO)) + LOG.info(pluginName + " deriving master secret"); return crypto.deriveMasterSecret(key, keyPair, alice); } - protected void sendConfirmation(Writer w) throws IOException, - InterruptedException { - boolean matched = group.waitForLocalConfirmationResult(); + protected void sendConfirmation(Writer w, boolean matched) + throws IOException { w.writeBoolean(matched); w.flush(); - if(LOG.isLoggable(INFO)) LOG.info(pluginName + " sent confirmation"); + if(LOG.isLoggable(INFO)) + LOG.info(pluginName + " sent confirmation: " + matched); } protected boolean receiveConfirmation(Reader r) throws IOException { boolean matched = r.readBoolean(); if(LOG.isLoggable(INFO)) - LOG.info(pluginName + " received confirmation"); + LOG.info(pluginName + " received confirmation: " + matched); return matched; } diff --git a/briar-core/src/net/sf/briar/invitation/ConnectorGroup.java b/briar-core/src/net/sf/briar/invitation/ConnectorGroup.java index 47f0beb6053c9dd1f7b9b3509cae760ca40449f9..ee67e4ccd3431f6b36aa39e5ad89c240791dfa0f 100644 --- a/briar-core/src/net/sf/briar/invitation/ConnectorGroup.java +++ b/briar-core/src/net/sf/briar/invitation/ConnectorGroup.java @@ -197,15 +197,15 @@ class ConnectorGroup extends Thread implements InvitationTask { public void localConfirmationFailed() { synchronized(this) { localCompared = true; + localMatched = false; } localConfirmationLatch.countDown(); } boolean getAndSetConnected() { boolean redundant = connected.getAndSet(true); - if(!redundant) { + if(!redundant) for(InvitationListener l : listeners) l.connectionSucceeded(); - } return redundant; } @@ -222,6 +222,13 @@ class ConnectorGroup extends Thread implements InvitationTask { for(InvitationListener l : listeners) l.keyAgreementFailed(); } + boolean waitForLocalConfirmationResult() throws InterruptedException { + localConfirmationLatch.await(CONFIRMATION_TIMEOUT, MILLISECONDS); + synchronized(this) { + return localMatched; + } + } + void remoteConfirmationSucceeded() { synchronized(this) { remoteCompared = true; @@ -233,17 +240,11 @@ class ConnectorGroup extends Thread implements InvitationTask { void remoteConfirmationFailed() { synchronized(this) { remoteCompared = true; + remoteMatched = false; } for(InvitationListener l : listeners) l.remoteConfirmationFailed(); } - boolean waitForLocalConfirmationResult() throws InterruptedException { - localConfirmationLatch.await(CONFIRMATION_TIMEOUT, MILLISECONDS); - synchronized(this) { - return localMatched; - } - } - void pseudonymExchangeSucceeded(Author remoteAuthor) { String name = remoteAuthor.getName(); synchronized(this) {