Invitation protocol was proceeding after confirmation timed out.

Both sides now close the connection after exchanging confirmation
results unless both results are positive.
This commit is contained in:
akwizgran
2013-05-16 15:10:16 +01:00
parent 91ccdfd8d7
commit 1692e5a695
5 changed files with 48 additions and 28 deletions

View File

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

View File

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

View File

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

View File

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

View File

@@ -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) {