From dddd15cd10239e1cfcc97694ac029870e1828f63 Mon Sep 17 00:00:00 2001 From: akwizgran <michael@briarproject.org> Date: Tue, 14 May 2013 20:54:23 +0100 Subject: [PATCH] Fixed a race conditon when adding a transport and then an endpoint. To fix issue #3611966, KeyManagerImpl's handling of TransportAddedEvent was made asynchronous. This made it possible for a thread to call KeyManager.endpointAdded() before the KeyManager had asynchronously handled the TransportAddedEvent from a previous call to DatabaseComponent.addTransport(). --- .../src/net/sf/briar/api/crypto/KeyManager.java | 2 +- .../src/net/sf/briar/invitation/Connector.java | 14 ++++++++++---- .../src/net/sf/briar/transport/KeyManagerImpl.java | 10 +++------- briar-tests/build.xml | 2 +- .../simplex/SimplexMessagingIntegrationTest.java | 4 ++-- .../net/sf/briar/transport/KeyManagerImplTest.java | 4 ++-- .../transport/KeyRotationIntegrationTest.java | 6 +++--- 7 files changed, 22 insertions(+), 20 deletions(-) diff --git a/briar-api/src/net/sf/briar/api/crypto/KeyManager.java b/briar-api/src/net/sf/briar/api/crypto/KeyManager.java index 8964f665f8..781ad3b139 100644 --- a/briar-api/src/net/sf/briar/api/crypto/KeyManager.java +++ b/briar-api/src/net/sf/briar/api/crypto/KeyManager.java @@ -27,5 +27,5 @@ public interface KeyManager { * Called whenever an endpoint has been added. The initial secret * is erased before returning. */ - void endpointAdded(Endpoint ep, byte[] initialSecret); + void endpointAdded(Endpoint ep, long maxLatency, byte[] initialSecret); } diff --git a/briar-core/src/net/sf/briar/invitation/Connector.java b/briar-core/src/net/sf/briar/invitation/Connector.java index e54f1518d8..c58d9d4b3c 100644 --- a/briar-core/src/net/sf/briar/invitation/Connector.java +++ b/briar-core/src/net/sf/briar/invitation/Connector.java @@ -288,19 +288,25 @@ abstract class Connector extends Thread { db.setRemoteProperties(contactId, remoteProps); // Create an endpoint for each transport shared with the contact List<TransportId> ids = new ArrayList<TransportId>(); - for(TransportId id : localProps.keySet()) - if(remoteProps.containsKey(id)) ids.add(id); + Map<TransportId, Long> latencies = db.getTransportLatencies(); + for(TransportId id : localProps.keySet()) { + if(latencies.containsKey(id) && remoteProps.containsKey(id)) + ids.add(id); + } // Assign indices to the transports deterministically and derive keys Collections.sort(ids, TransportIdComparator.INSTANCE); int size = ids.size(); for(int i = 0; i < size; i++) { - Endpoint ep = new Endpoint(contactId, ids.get(i), epoch, alice); + TransportId id = ids.get(i); + Endpoint ep = new Endpoint(contactId, id, epoch, alice); + long maxLatency = latencies.get(id); try { db.addEndpoint(ep); } catch(NoSuchTransportException e) { continue; } - keyManager.endpointAdded(ep, crypto.deriveInitialSecret(secret, i)); + byte[] initialSecret = crypto.deriveInitialSecret(secret, i); + keyManager.endpointAdded(ep, maxLatency, initialSecret); } } diff --git a/briar-core/src/net/sf/briar/transport/KeyManagerImpl.java b/briar-core/src/net/sf/briar/transport/KeyManagerImpl.java index 9597af9ca0..778607b9a3 100644 --- a/briar-core/src/net/sf/briar/transport/KeyManagerImpl.java +++ b/briar-core/src/net/sf/briar/transport/KeyManagerImpl.java @@ -252,13 +252,9 @@ class KeyManagerImpl extends TimerTask implements KeyManager, DatabaseListener { return new ConnectionContext(c, t, secret, connection, s.getAlice()); } - public synchronized void endpointAdded(Endpoint ep, byte[] initialSecret) { - Long maxLatency = maxLatencies.get(ep.getTransportId()); - if(maxLatency == null) { - if(LOG.isLoggable(INFO)) - LOG.info("No such transport, ignoring endpoint"); - return; - } + public synchronized void endpointAdded(Endpoint ep, long maxLatency, + byte[] initialSecret) { + maxLatencies.put(ep.getTransportId(), maxLatency); // Work out which rotation period we're in long elapsed = clock.currentTimeMillis() - ep.getEpoch(); long rotation = maxLatency + MAX_CLOCK_DIFFERENCE; diff --git a/briar-tests/build.xml b/briar-tests/build.xml index 655e6f80ed..e2d8d749fb 100644 --- a/briar-tests/build.xml +++ b/briar-tests/build.xml @@ -55,7 +55,7 @@ </javac> </target> <target name='test' depends='compile'> - <junit printsummary='on' fork='yes' forkmode='once'> + <junit showoutput='yes' printsummary='on' fork='yes' forkmode='once'> <assertions> <enable/> </assertions> diff --git a/briar-tests/src/net/sf/briar/messaging/simplex/SimplexMessagingIntegrationTest.java b/briar-tests/src/net/sf/briar/messaging/simplex/SimplexMessagingIntegrationTest.java index 3d4c0bc6ad..882245d819 100644 --- a/briar-tests/src/net/sf/briar/messaging/simplex/SimplexMessagingIntegrationTest.java +++ b/briar-tests/src/net/sf/briar/messaging/simplex/SimplexMessagingIntegrationTest.java @@ -125,7 +125,7 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase { db.addTransport(transportId, LATENCY); Endpoint ep = new Endpoint(contactId, transportId, epoch, true); db.addEndpoint(ep); - km.endpointAdded(ep, initialSecret.clone()); + km.endpointAdded(ep, LATENCY, initialSecret.clone()); // Send Bob a message String contentType = "text/plain"; byte[] body = "Hi Bob!".getBytes("UTF-8"); @@ -179,7 +179,7 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase { db.addTransport(transportId, LATENCY); Endpoint ep = new Endpoint(contactId, transportId, epoch, false); db.addEndpoint(ep); - km.endpointAdded(ep, initialSecret.clone()); + km.endpointAdded(ep, LATENCY, initialSecret.clone()); // Set up a database listener MessageListener listener = new MessageListener(); db.addListener(listener); diff --git a/briar-tests/src/net/sf/briar/transport/KeyManagerImplTest.java b/briar-tests/src/net/sf/briar/transport/KeyManagerImplTest.java index 0f7bed504b..32b418f796 100644 --- a/briar-tests/src/net/sf/briar/transport/KeyManagerImplTest.java +++ b/briar-tests/src/net/sf/briar/transport/KeyManagerImplTest.java @@ -141,7 +141,7 @@ public class KeyManagerImplTest extends BriarTestCase { }}); assertTrue(keyManager.start()); - keyManager.endpointAdded(ep, initialSecret.clone()); + keyManager.endpointAdded(ep, MAX_LATENCY, initialSecret.clone()); keyManager.stop(); context.assertIsSatisfied(); @@ -202,7 +202,7 @@ public class KeyManagerImplTest extends BriarTestCase { }}); assertTrue(keyManager.start()); - keyManager.endpointAdded(ep, initialSecret.clone()); + keyManager.endpointAdded(ep, MAX_LATENCY, initialSecret.clone()); ConnectionContext ctx = keyManager.getConnectionContext(contactId, transportId); assertNotNull(ctx); diff --git a/briar-tests/src/net/sf/briar/transport/KeyRotationIntegrationTest.java b/briar-tests/src/net/sf/briar/transport/KeyRotationIntegrationTest.java index 380c95c1ed..93dfb3b429 100644 --- a/briar-tests/src/net/sf/briar/transport/KeyRotationIntegrationTest.java +++ b/briar-tests/src/net/sf/briar/transport/KeyRotationIntegrationTest.java @@ -239,7 +239,7 @@ public class KeyRotationIntegrationTest extends BriarTestCase { }}); assertTrue(keyManager.start()); - keyManager.endpointAdded(ep, initialSecret.clone()); + keyManager.endpointAdded(ep, MAX_LATENCY, initialSecret.clone()); keyManager.stop(); context.assertIsSatisfied(); @@ -377,7 +377,7 @@ public class KeyRotationIntegrationTest extends BriarTestCase { }}); assertTrue(keyManager.start()); - keyManager.endpointAdded(ep, initialSecret.clone()); + keyManager.endpointAdded(ep, MAX_LATENCY, initialSecret.clone()); ConnectionContext ctx = keyManager.getConnectionContext(contactId, transportId); assertNotNull(ctx); @@ -533,7 +533,7 @@ public class KeyRotationIntegrationTest extends BriarTestCase { }}); assertTrue(keyManager.start()); - keyManager.endpointAdded(ep, initialSecret.clone()); + keyManager.endpointAdded(ep, MAX_LATENCY, initialSecret.clone()); // Recognise the tag for connection 0 in period 2 byte[] tag = new byte[TAG_LENGTH]; encodeTag(tag, key2, 0); -- GitLab