From 1692e5a6950671fe7b31ef38c088d018c298966c Mon Sep 17 00:00:00 2001 From: akwizgran <michael@briarproject.org> Date: Thu, 16 May 2013 15:10:16 +0100 Subject: [PATCH] Invitation protocol was proceeding after confirmation timed out. Both sides now close the connection after exchanging confirmation results unless both results are positive. --- .../invitation/AddContactActivity.java | 3 +++ .../sf/briar/invitation/AliceConnector.java | 21 ++++++++++++------- .../net/sf/briar/invitation/BobConnector.java | 21 ++++++++++++------- .../net/sf/briar/invitation/Connector.java | 12 ++++++----- .../sf/briar/invitation/ConnectorGroup.java | 19 +++++++++-------- 5 files changed, 48 insertions(+), 28 deletions(-) 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 14798d6255..6c22e433c5 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 580195cd1c..6337959617 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 8d7d2ad09f..3f03a65b61 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 c58d9d4b3c..f0fd6b0955 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 47f0beb605..ee67e4ccd3 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) { -- GitLab