diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/account/AccountManager.java b/bramble-api/src/main/java/org/briarproject/bramble/api/account/AccountManager.java index 4aa4fb2b5..e1efc91dc 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/account/AccountManager.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/account/AccountManager.java @@ -1,6 +1,22 @@ package org.briarproject.bramble.api.account; +import org.briarproject.bramble.api.crypto.SecretKey; +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; + +import javax.annotation.Nullable; + +@NotNullByDefault public interface AccountManager { boolean hasDatabaseKey(); + + @Nullable + SecretKey getDatabaseKey(); + + void setDatabaseKey(SecretKey k); + + @Nullable + String getEncryptedDatabaseKey(); + + boolean storeEncryptedDatabaseKey(String hex); } diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java index 914b88a2e..f4161cee4 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java @@ -2,6 +2,7 @@ package org.briarproject.bramble.api.db; import org.briarproject.bramble.api.contact.Contact; import org.briarproject.bramble.api.contact.ContactId; +import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.identity.AuthorId; import org.briarproject.bramble.api.identity.LocalAuthor; @@ -44,7 +45,8 @@ public interface DatabaseComponent { * @throws DataTooOldException if the data uses an older schema than the * current code and cannot be migrated */ - boolean open(@Nullable MigrationListener listener) throws DbException; + boolean open(SecretKey key, @Nullable MigrationListener listener) + throws DbException; /** * Waits for any open transactions to finish and closes the database. @@ -267,7 +269,7 @@ public interface DatabaseComponent { * Read-only. */ Collection getMessageIds(Transaction txn, GroupId g) - throws DbException; + throws DbException; /** * Returns the IDs of any messages that need to be validated. @@ -487,7 +489,7 @@ public interface DatabaseComponent { * Removes the given transport keys from the database. */ void removeTransportKeys(Transaction txn, TransportId t, KeySetId k) - throws DbException; + throws DbException; /** * Marks the given contact as verified. @@ -534,7 +536,7 @@ public interface DatabaseComponent { * Marks the given transport keys as usable for outgoing streams. */ void setTransportKeysActive(Transaction txn, TransportId t, KeySetId k) - throws DbException; + throws DbException; /** * Stores the given transport keys, deleting any keys they have replaced. diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseConfig.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseConfig.java index e431c15f2..a9a95c47a 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseConfig.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseConfig.java @@ -1,12 +1,9 @@ package org.briarproject.bramble.api.db; -import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import java.io.File; -import javax.annotation.Nullable; - @NotNullByDefault public interface DatabaseConfig { @@ -16,10 +13,5 @@ public interface DatabaseConfig { File getDatabaseKeyDirectory(); - void setEncryptionKey(SecretKey key); - - @Nullable - SecretKey getEncryptionKey(); - long getMaxSize(); } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/account/AccountManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/account/AccountManagerImpl.java index dd4df479a..cbc813d71 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/account/AccountManagerImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/account/AccountManagerImpl.java @@ -1,21 +1,140 @@ package org.briarproject.bramble.account; import org.briarproject.bramble.api.account.AccountManager; +import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.db.DatabaseConfig; +import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; +import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.logging.Logger; + +import javax.annotation.Nullable; import javax.inject.Inject; +import static java.util.logging.Level.WARNING; +import static org.briarproject.bramble.util.LogUtils.logException; + +@MethodsNotNullByDefault +@ParametersNotNullByDefault class AccountManagerImpl implements AccountManager { + private static final Logger LOG = + Logger.getLogger(AccountManagerImpl.class.getName()); + + private static final String DB_KEY_FILENAME = "db.key"; + private static final String DB_KEY_BACKUP_FILENAME = "db.key.bak"; + private final DatabaseConfig databaseConfig; + private final File dbKeyFile, dbKeyBackupFile; + + @Nullable + private volatile SecretKey databaseKey = null; @Inject AccountManagerImpl(DatabaseConfig databaseConfig) { this.databaseConfig = databaseConfig; + File keyDir = databaseConfig.getDatabaseKeyDirectory(); + dbKeyFile = new File(keyDir, DB_KEY_FILENAME); + dbKeyBackupFile = new File(keyDir, DB_KEY_BACKUP_FILENAME); } @Override public boolean hasDatabaseKey() { - return databaseConfig.getEncryptionKey() != null; + return databaseKey != null; + } + + @Override + @Nullable + public SecretKey getDatabaseKey() { + return databaseKey; + } + + @Override + public void setDatabaseKey(SecretKey k) { + databaseKey = k; + } + + @Override + @Nullable + public String getEncryptedDatabaseKey() { + String key = readDbKeyFromFile(dbKeyFile); + if (key == null) { + LOG.info("No database key in primary file"); + key = readDbKeyFromFile(dbKeyBackupFile); + if (key == null) LOG.info("No database key in backup file"); + else LOG.warning("Found database key in backup file"); + } else { + LOG.info("Found database key in primary file"); + } + return key; + } + + @Nullable + private String readDbKeyFromFile(File f) { + if (!f.exists()) { + LOG.info("Key file does not exist"); + return null; + } + try { + BufferedReader reader = new BufferedReader(new InputStreamReader( + new FileInputStream(f), "UTF-8")); + String key = reader.readLine(); + reader.close(); + return key; + } catch (IOException e) { + logException(LOG, WARNING, e); + return null; + } + } + + @Override + public boolean storeEncryptedDatabaseKey(String hex) { + LOG.info("Storing database key in file"); + // Create the directory if necessary + if (databaseConfig.getDatabaseKeyDirectory().mkdirs()) + LOG.info("Created database key directory"); + // If only the backup file exists, rename it so we don't overwrite it + if (dbKeyBackupFile.exists() && !dbKeyFile.exists()) { + if (dbKeyBackupFile.renameTo(dbKeyFile)) + LOG.info("Renamed old backup"); + else LOG.warning("Failed to rename old backup"); + } + try { + // Write to the backup file + writeDbKeyToFile(hex, dbKeyBackupFile); + LOG.info("Stored database key in backup file"); + // Delete the old primary file, if it exists + if (dbKeyFile.exists()) { + if (dbKeyFile.delete()) LOG.info("Deleted primary file"); + else LOG.warning("Failed to delete primary file"); + } + // The backup file becomes the new primary + if (dbKeyBackupFile.renameTo(dbKeyFile)) { + LOG.info("Renamed backup file to primary"); + } else { + LOG.warning("Failed to rename backup file to primary"); + return false; // Don't overwrite our only copy + } + // Write a second copy to the backup file + writeDbKeyToFile(hex, dbKeyBackupFile); + LOG.info("Stored second copy of database key in backup file"); + return true; + } catch (IOException e) { + logException(LOG, WARNING, e); + return false; + } + } + + private void writeDbKeyToFile(String key, File f) throws IOException { + FileOutputStream out = new FileOutputStream(f); + out.write(key.getBytes("UTF-8")); + out.flush(); + out.close(); } } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java b/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java index 66e5cfcf6..796e4bbe4 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java @@ -2,6 +2,7 @@ package org.briarproject.bramble.db; import org.briarproject.bramble.api.contact.Contact; import org.briarproject.bramble.api.contact.ContactId; +import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.db.DataTooNewException; import org.briarproject.bramble.api.db.DataTooOldException; import org.briarproject.bramble.api.db.DbException; @@ -48,7 +49,8 @@ interface Database { * @throws DataTooOldException if the data uses an older schema than the * current code and cannot be migrated */ - boolean open(@Nullable MigrationListener listener) throws DbException; + boolean open(SecretKey key, @Nullable MigrationListener listener) + throws DbException; /** * Prevents new transactions from starting, waits for all current @@ -641,7 +643,7 @@ interface Database { * Marks the given transport keys as usable for outgoing streams. */ void setTransportKeysActive(T txn, TransportId t, KeySetId k) - throws DbException; + throws DbException; /** * Updates the transmission count and expiry time of the given message diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java index f2e4de1c6..2913c783f 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java @@ -6,6 +6,7 @@ import org.briarproject.bramble.api.contact.event.ContactAddedEvent; import org.briarproject.bramble.api.contact.event.ContactRemovedEvent; import org.briarproject.bramble.api.contact.event.ContactStatusChangedEvent; import org.briarproject.bramble.api.contact.event.ContactVerifiedEvent; +import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.db.ContactExistsException; import org.briarproject.bramble.api.db.DatabaseComponent; import org.briarproject.bramble.api.db.DbException; @@ -103,9 +104,9 @@ class DatabaseComponentImpl implements DatabaseComponent { } @Override - public boolean open(@Nullable MigrationListener listener) + public boolean open(SecretKey key, @Nullable MigrationListener listener) throws DbException { - boolean reopened = db.open(listener); + boolean reopened = db.open(key, listener); shutdown.addShutdownHook(() -> { try { close(); diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/H2Database.java b/bramble-core/src/main/java/org/briarproject/bramble/db/H2Database.java index 1c1983e67..fd5be6905 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/H2Database.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/H2Database.java @@ -32,6 +32,9 @@ class H2Database extends JdbcDatabase { private final DatabaseConfig config; private final String url; + @Nullable + private volatile SecretKey key = null; + @Inject H2Database(DatabaseConfig config, Clock clock) { super(HASH_TYPE, SECRET_TYPE, BINARY_TYPE, COUNTER_TYPE, STRING_TYPE, @@ -44,11 +47,12 @@ class H2Database extends JdbcDatabase { } @Override - public boolean open(@Nullable MigrationListener listener) + public boolean open(SecretKey key, @Nullable MigrationListener listener) throws DbException { + this.key = key; boolean reopen = config.databaseExists(); if (!reopen) config.getDatabaseDirectory().mkdirs(); - super.open("org.h2.Driver", reopen, listener); + super.open("org.h2.Driver", reopen, key, listener); return reopen; } @@ -63,7 +67,7 @@ class H2Database extends JdbcDatabase { } @Override - public long getFreeSpace() throws DbException { + public long getFreeSpace() { File dir = config.getDatabaseDirectory(); long maxSize = config.getMaxSize(); long free = dir.getFreeSpace(); @@ -88,7 +92,7 @@ class H2Database extends JdbcDatabase { @Override protected Connection createConnection() throws SQLException { - SecretKey key = config.getEncryptionKey(); + SecretKey key = this.key; if (key == null) throw new IllegalStateException(); Properties props = new Properties(); props.setProperty("user", "user"); diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/HyperSqlDatabase.java b/bramble-core/src/main/java/org/briarproject/bramble/db/HyperSqlDatabase.java index 6a87ededa..0bfb66ea6 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/HyperSqlDatabase.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/HyperSqlDatabase.java @@ -33,6 +33,9 @@ class HyperSqlDatabase extends JdbcDatabase { private final DatabaseConfig config; private final String url; + @Nullable + private volatile SecretKey key = null; + @Inject HyperSqlDatabase(DatabaseConfig config, Clock clock) { super(HASH_TYPE, SECRET_TYPE, BINARY_TYPE, COUNTER_TYPE, STRING_TYPE, @@ -46,10 +49,12 @@ class HyperSqlDatabase extends JdbcDatabase { } @Override - public boolean open(@Nullable MigrationListener listener) throws DbException { + public boolean open(SecretKey key, @Nullable MigrationListener listener) + throws DbException { + this.key = key; boolean reopen = config.databaseExists(); if (!reopen) config.getDatabaseDirectory().mkdirs(); - super.open("org.hsqldb.jdbc.JDBCDriver", reopen, listener); + super.open("org.hsqldb.jdbc.JDBCDriver", reopen, key, listener); return reopen; } @@ -93,7 +98,7 @@ class HyperSqlDatabase extends JdbcDatabase { @Override protected Connection createConnection() throws SQLException { - SecretKey key = config.getEncryptionKey(); + SecretKey key = this.key; if (key == null) throw new IllegalStateException(); String hex = StringUtils.toHexString(key.getBytes()); return DriverManager.getConnection(url + ";crypt_key=" + hex); diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java b/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java index baa67a29a..fd248f811 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java @@ -328,7 +328,7 @@ abstract class JdbcDatabase implements Database { this.clock = clock; } - protected void open(String driverClass, boolean reopen, + protected void open(String driverClass, boolean reopen, SecretKey key, @Nullable MigrationListener listener) throws DbException { // Load the JDBC driver try { diff --git a/bramble-core/src/main/java/org/briarproject/bramble/lifecycle/LifecycleManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/lifecycle/LifecycleManagerImpl.java index b99ab31e1..a2c4d7e3f 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/lifecycle/LifecycleManagerImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/lifecycle/LifecycleManagerImpl.java @@ -1,5 +1,7 @@ package org.briarproject.bramble.lifecycle; +import org.briarproject.bramble.api.account.AccountManager; +import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.db.DataTooNewException; import org.briarproject.bramble.api.db.DataTooOldException; import org.briarproject.bramble.api.db.DatabaseComponent; @@ -55,6 +57,7 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener { private final List services; private final List clients; private final List executors; + private final AccountManager accountManager; private final IdentityManager identityManager; private final Semaphore startStopSemaphore = new Semaphore(1); private final CountDownLatch dbLatch = new CountDownLatch(1); @@ -65,9 +68,10 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener { @Inject LifecycleManagerImpl(DatabaseComponent db, EventBus eventBus, - IdentityManager identityManager) { + AccountManager accountManager, IdentityManager identityManager) { this.db = db; this.eventBus = eventBus; + this.accountManager = accountManager; this.identityManager = identityManager; services = new CopyOnWriteArrayList<>(); clients = new CopyOnWriteArrayList<>(); @@ -104,7 +108,9 @@ class LifecycleManagerImpl implements LifecycleManager, MigrationListener { LOG.info("Starting services"); long start = now(); - boolean reopened = db.open(this); + SecretKey key = accountManager.getDatabaseKey(); + if (key == null) throw new IllegalStateException(); + boolean reopened = db.open(key, this); if (reopened) logDuration(LOG, "Reopening database", start); else logDuration(LOG, "Creating database", start); identityManager.storeLocalAuthor(); diff --git a/bramble-core/src/test/java/org/briarproject/bramble/account/AccountManagerImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/account/AccountManagerImplTest.java new file mode 100644 index 000000000..7e1f6124d --- /dev/null +++ b/bramble-core/src/test/java/org/briarproject/bramble/account/AccountManagerImplTest.java @@ -0,0 +1,158 @@ +package org.briarproject.bramble.account; + +import org.briarproject.bramble.api.db.DatabaseConfig; +import org.briarproject.bramble.test.BrambleMockTestCase; +import org.jmock.Expectations; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; + +import javax.annotation.Nullable; + +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertNull; +import static junit.framework.Assert.assertTrue; +import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory; +import static org.briarproject.bramble.test.TestUtils.getRandomBytes; +import static org.briarproject.bramble.test.TestUtils.getTestDirectory; +import static org.briarproject.bramble.util.StringUtils.toHexString; +import static org.junit.Assert.assertEquals; + +public class AccountManagerImplTest extends BrambleMockTestCase { + + private final DatabaseConfig databaseConfig = + context.mock(DatabaseConfig.class); + + private final byte[] encryptedKey = getRandomBytes(123); + private final String encryptedKeyHex = toHexString(encryptedKey); + private final String oldEncryptedKeyHex = toHexString(getRandomBytes(123)); + private final File testDir = getTestDirectory(); + private final File keyDir = new File(testDir, "key"); + private final File keyFile = new File(keyDir, "db.key"); + private final File keyBackupFile = new File(keyDir, "db.key.bak"); + + private AccountManagerImpl accountManager; + + @Before + public void setUp() { + context.checking(new Expectations() {{ + allowing(databaseConfig).getDatabaseKeyDirectory(); + will(returnValue(keyDir)); + }}); + accountManager = new AccountManagerImpl(databaseConfig); + } + + @Test + public void testDbKeyIsLoadedFromPrimaryFile() throws Exception { + assertFalse(keyFile.exists()); + assertFalse(keyBackupFile.exists()); + + storeDatabaseKey(keyFile, encryptedKeyHex); + + assertTrue(keyFile.exists()); + assertFalse(keyBackupFile.exists()); + assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile)); + + assertEquals(encryptedKeyHex, accountManager.getEncryptedDatabaseKey()); + + assertTrue(keyFile.exists()); + assertFalse(keyBackupFile.exists()); + assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile)); + } + + @Test + public void testDbKeyIsLoadedFromBackupFile() throws Exception { + assertFalse(keyFile.exists()); + assertFalse(keyBackupFile.exists()); + + storeDatabaseKey(keyBackupFile, encryptedKeyHex); + + assertFalse(keyFile.exists()); + assertTrue(keyBackupFile.exists()); + assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile)); + + assertEquals(encryptedKeyHex, accountManager.getEncryptedDatabaseKey()); + + assertFalse(keyFile.exists()); + assertTrue(keyBackupFile.exists()); + assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile)); + } + + @Test + public void testDbKeyIsNullIfNotFound() { + assertFalse(keyFile.exists()); + assertFalse(keyBackupFile.exists()); + + assertNull(accountManager.getEncryptedDatabaseKey()); + + assertFalse(keyFile.exists()); + assertFalse(keyBackupFile.exists()); + } + + @Test + public void testStoringDbKeyOverwritesPrimary() throws Exception { + assertFalse(keyFile.exists()); + assertFalse(keyBackupFile.exists()); + + storeDatabaseKey(keyFile, oldEncryptedKeyHex); + + assertTrue(keyFile.exists()); + assertFalse(keyBackupFile.exists()); + assertEquals(oldEncryptedKeyHex, loadDatabaseKey(keyFile)); + + assertTrue(accountManager.storeEncryptedDatabaseKey(encryptedKeyHex)); + + assertTrue(keyFile.exists()); + assertTrue(keyBackupFile.exists()); + assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile)); + assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile)); + } + + @Test + public void testStoringDbKeyOverwritesBackup() throws Exception { + assertFalse(keyFile.exists()); + assertFalse(keyBackupFile.exists()); + + storeDatabaseKey(keyBackupFile, oldEncryptedKeyHex); + + assertFalse(keyFile.exists()); + assertTrue(keyBackupFile.exists()); + assertEquals(oldEncryptedKeyHex, loadDatabaseKey(keyBackupFile)); + + assertTrue(accountManager.storeEncryptedDatabaseKey(encryptedKeyHex)); + + assertTrue(keyFile.exists()); + assertTrue(keyBackupFile.exists()); + assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile)); + assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile)); + } + + @After + public void tearDown() { + deleteTestDirectory(testDir); + } + + private void storeDatabaseKey(File f, String hex) throws IOException { + f.getParentFile().mkdirs(); + FileOutputStream out = new FileOutputStream(f); + out.write(hex.getBytes("UTF-8")); + out.flush(); + out.close(); + } + + @Nullable + private String loadDatabaseKey(File f) throws IOException { + BufferedReader reader = new BufferedReader(new InputStreamReader( + new FileInputStream(f), "UTF-8")); + String hex = reader.readLine(); + reader.close(); + return hex; + } +} diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java index e16e03da0..676cac2e3 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java @@ -89,6 +89,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase { context.mock(ShutdownManager.class); private final EventBus eventBus = context.mock(EventBus.class); + private final SecretKey key = getSecretKey(); private final Object txn = new Object(); private final ClientId clientId; private final int majorVersion; @@ -141,7 +142,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase { int shutdownHandle = 12345; context.checking(new Expectations() {{ // open() - oneOf(database).open(null); + oneOf(database).open(key, null); will(returnValue(false)); oneOf(shutdown).addShutdownHook(with(any(Runnable.class))); will(returnValue(shutdownHandle)); @@ -208,7 +209,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase { DatabaseComponent db = createDatabaseComponent(database, eventBus, shutdown); - assertFalse(db.open(null)); + assertFalse(db.open(key, null)); Transaction transaction = db.startTransaction(false); try { db.addLocalAuthor(transaction, localAuthor); @@ -1602,7 +1603,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase { MessageId messageId2 = new MessageId(getRandomId()); context.checking(new Expectations() {{ // open() - oneOf(database).open(null); + oneOf(database).open(key, null); will(returnValue(false)); oneOf(shutdown).addShutdownHook(with(any(Runnable.class))); will(returnValue(shutdownHandle)); @@ -1646,7 +1647,7 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase { DatabaseComponent db = createDatabaseComponent(database, eventBus, shutdown); - assertFalse(db.open(null)); + assertFalse(db.open(key, null)); Transaction transaction = db.startTransaction(false); try { db.addLocalMessage(transaction, message, metadata, true); diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseMigrationTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseMigrationTest.java index 89bdf8a4c..0740bdfc2 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseMigrationTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseMigrationTest.java @@ -1,5 +1,6 @@ package org.briarproject.bramble.db; +import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.db.DataTooNewException; import org.briarproject.bramble.api.db.DataTooOldException; import org.briarproject.bramble.api.db.DatabaseConfig; @@ -26,6 +27,7 @@ import static java.util.Collections.singletonList; import static org.briarproject.bramble.db.DatabaseConstants.DB_SETTINGS_NAMESPACE; import static org.briarproject.bramble.db.DatabaseConstants.SCHEMA_VERSION_KEY; import static org.briarproject.bramble.db.JdbcDatabase.CODE_SCHEMA_VERSION; +import static org.briarproject.bramble.test.TestUtils.getSecretKey; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -43,6 +45,7 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase { protected final DatabaseConfig config = new TestDatabaseConfig(testDir, 1024 * 1024); + protected final SecretKey key = getSecretKey(); protected final Clock clock = new SystemClock(); abstract Database createDatabase( @@ -62,7 +65,7 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase { public void testDoesNotRunMigrationsWhenCreatingDatabase() throws Exception { Database db = createDatabase(singletonList(migration)); - assertFalse(db.open(null)); + assertFalse(db.open(key, null)); assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db)); db.close(); } @@ -72,14 +75,14 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase { throws Exception { // Open the DB for the first time Database db = createDatabase(asList(migration, migration1)); - assertFalse(db.open(null)); + assertFalse(db.open(key, null)); assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db)); // Override the data schema version setDataSchemaVersion(db, -1); db.close(); // Reopen the DB - an exception should be thrown db = createDatabase(asList(migration, migration1)); - db.open(null); + db.open(key, null); } @Test @@ -87,12 +90,12 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase { throws Exception { // Open the DB for the first time Database db = createDatabase(asList(migration, migration1)); - assertFalse(db.open(null)); + assertFalse(db.open(key, null)); assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db)); db.close(); // Reopen the DB - migrations should not be run db = createDatabase(asList(migration, migration1)); - assertTrue(db.open(null)); + assertTrue(db.open(key, null)); assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db)); db.close(); } @@ -101,14 +104,14 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase { public void testThrowsExceptionIfDataIsNewerThanCode() throws Exception { // Open the DB for the first time Database db = createDatabase(asList(migration, migration1)); - assertFalse(db.open(null)); + assertFalse(db.open(key, null)); assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db)); // Override the data schema version setDataSchemaVersion(db, CODE_SCHEMA_VERSION + 1); db.close(); // Reopen the DB - an exception should be thrown db = createDatabase(asList(migration, migration1)); - db.open(null); + db.open(key, null); } @Test(expected = DataTooOldException.class) @@ -116,13 +119,13 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase { throws Exception { // Open the DB for the first time Database db = createDatabase(emptyList()); - assertFalse(db.open(null)); + assertFalse(db.open(key, null)); assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db)); setDataSchemaVersion(db, CODE_SCHEMA_VERSION - 1); db.close(); // Reopen the DB - an exception should be thrown db = createDatabase(emptyList()); - db.open(null); + db.open(key, null); } @Test(expected = DataTooOldException.class) @@ -141,14 +144,14 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase { // Open the DB for the first time Database db = createDatabase(asList(migration, migration1)); - assertFalse(db.open(null)); + assertFalse(db.open(key, null)); assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db)); // Override the data schema version setDataSchemaVersion(db, CODE_SCHEMA_VERSION - 3); db.close(); // Reopen the DB - an exception should be thrown db = createDatabase(asList(migration, migration1)); - db.open(null); + db.open(key, null); } @Test @@ -170,14 +173,14 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase { // Open the DB for the first time Database db = createDatabase(asList(migration, migration1)); - assertFalse(db.open(null)); + assertFalse(db.open(key, null)); assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db)); // Override the data schema version setDataSchemaVersion(db, CODE_SCHEMA_VERSION - 2); db.close(); // Reopen the DB - the first migration should be run db = createDatabase(asList(migration, migration1)); - assertTrue(db.open(null)); + assertTrue(db.open(key, null)); assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db)); db.close(); } @@ -202,14 +205,14 @@ public abstract class DatabaseMigrationTest extends BrambleMockTestCase { // Open the DB for the first time Database db = createDatabase(asList(migration, migration1)); - assertFalse(db.open(null)); + assertFalse(db.open(key, null)); assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db)); // Override the data schema version setDataSchemaVersion(db, CODE_SCHEMA_VERSION - 2); db.close(); // Reopen the DB - both migrations should be run db = createDatabase(asList(migration, migration1)); - assertTrue(db.open(null)); + assertTrue(db.open(key, null)); assertEquals(CODE_SCHEMA_VERSION, getDataSchemaVersion(db)); db.close(); } diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabasePerformanceComparisonTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabasePerformanceComparisonTest.java index 1807d30dc..279d1b56e 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabasePerformanceComparisonTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabasePerformanceComparisonTest.java @@ -15,6 +15,7 @@ import java.util.List; import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory; import static org.briarproject.bramble.test.TestUtils.getMean; import static org.briarproject.bramble.test.TestUtils.getMedian; +import static org.briarproject.bramble.test.TestUtils.getSecretKey; import static org.briarproject.bramble.test.TestUtils.getStandardDeviation; import static org.briarproject.bramble.test.UTest.Z_CRITICAL_0_01; @@ -71,7 +72,7 @@ public abstract class DatabasePerformanceComparisonTest throws DbException { Database db = createDatabase(conditionA, new TestDatabaseConfig(testDir, MAX_SIZE), new SystemClock()); - db.open(null); + db.open(getSecretKey(), null); return db; } diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseTraceTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseTraceTest.java index f4e0daa19..2060ca71e 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseTraceTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseTraceTest.java @@ -16,6 +16,7 @@ import java.sql.Connection; import javax.annotation.Nullable; import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory; +import static org.briarproject.bramble.test.TestUtils.getSecretKey; public abstract class DatabaseTraceTest extends DatabasePerformanceTest { @@ -43,7 +44,7 @@ public abstract class DatabaseTraceTest extends DatabasePerformanceTest { private Database openDatabase() throws DbException { Database db = createDatabase( new TestDatabaseConfig(testDir, MAX_SIZE), new SystemClock()); - db.open(null); + db.open(getSecretKey(), null); return db; } diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/H2MigrationTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/H2MigrationTest.java index 6a868fd42..29bdbfa5f 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/db/H2MigrationTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/db/H2MigrationTest.java @@ -9,8 +9,8 @@ import java.util.List; public class H2MigrationTest extends DatabaseMigrationTest { @Override - Database createDatabase(List> migrations) - throws Exception { + Database createDatabase( + List> migrations) { return new H2Database(config, clock) { @Override List> getMigrations() { diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java index 2655e9ef7..e88038258 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java @@ -64,6 +64,7 @@ import static org.briarproject.bramble.test.TestUtils.getLocalAuthor; import static org.briarproject.bramble.test.TestUtils.getRandomBytes; import static org.briarproject.bramble.test.TestUtils.getRandomId; import static org.briarproject.bramble.test.TestUtils.getSecretKey; +import static org.briarproject.bramble.test.TestUtils.getTestDirectory; import static org.briarproject.bramble.test.TestUtils.getTransportId; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -79,7 +80,8 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase { private static final int ONE_MEGABYTE = 1024 * 1024; private static final int MAX_SIZE = 5 * ONE_MEGABYTE; - private final File testDir = TestUtils.getTestDirectory(); + private final SecretKey key = getSecretKey(); + private final File testDir = getTestDirectory(); private final GroupId groupId; private final ClientId clientId; private final int majorVersion; @@ -96,7 +98,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase { private final KeySetId keySetId, keySetId1; private final Random random = new Random(); - JdbcDatabaseTest() throws Exception { + JdbcDatabaseTest() { clientId = getClientId(); majorVersion = 123; group = getGroup(clientId, majorVersion); @@ -1819,7 +1821,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase { Database db = createDatabase( new TestDatabaseConfig(testDir, MAX_SIZE), clock); if (!resume) TestUtils.deleteTestDirectory(testDir); - db.open(null); + db.open(key, null); return db; } diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/SingleDatabasePerformanceTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/SingleDatabasePerformanceTest.java index 670c7cddb..6256d39cd 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/db/SingleDatabasePerformanceTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/db/SingleDatabasePerformanceTest.java @@ -13,6 +13,7 @@ import java.util.List; import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory; import static org.briarproject.bramble.test.TestUtils.getMean; import static org.briarproject.bramble.test.TestUtils.getMedian; +import static org.briarproject.bramble.test.TestUtils.getSecretKey; import static org.briarproject.bramble.test.TestUtils.getStandardDeviation; public abstract class SingleDatabasePerformanceTest @@ -40,7 +41,7 @@ public abstract class SingleDatabasePerformanceTest private Database openDatabase() throws DbException { Database db = createDatabase( new TestDatabaseConfig(testDir, MAX_SIZE), new SystemClock()); - db.open(null); + db.open(getSecretKey(), null); return db; } diff --git a/bramble-core/src/test/java/org/briarproject/bramble/test/TestDatabaseConfig.java b/bramble-core/src/test/java/org/briarproject/bramble/test/TestDatabaseConfig.java index 7e5ad34e7..89f68a30e 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/test/TestDatabaseConfig.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/test/TestDatabaseConfig.java @@ -1,6 +1,5 @@ package org.briarproject.bramble.test; -import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.db.DatabaseConfig; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; @@ -11,7 +10,6 @@ public class TestDatabaseConfig implements DatabaseConfig { private final File dbDir, keyDir; private final long maxSize; - private volatile SecretKey key = new SecretKey(new byte[SecretKey.LENGTH]); public TestDatabaseConfig(File testDir, long maxSize) { dbDir = new File(testDir, "db"); @@ -36,16 +34,6 @@ public class TestDatabaseConfig implements DatabaseConfig { return keyDir; } - @Override - public void setEncryptionKey(SecretKey key) { - this.key = key; - } - - @Override - public SecretKey getEncryptionKey() { - return key; - } - @Override public long getMaxSize() { return maxSize; diff --git a/briar-android/src/main/java/org/briarproject/briar/android/AndroidDatabaseConfig.java b/briar-android/src/main/java/org/briarproject/briar/android/AndroidDatabaseConfig.java index 1f21acdb0..9aa2ac6ae 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/AndroidDatabaseConfig.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/AndroidDatabaseConfig.java @@ -1,14 +1,11 @@ package org.briarproject.briar.android; -import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.db.DatabaseConfig; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import java.io.File; import java.util.logging.Logger; -import javax.annotation.Nullable; - import static java.util.logging.Level.INFO; @NotNullByDefault @@ -19,9 +16,6 @@ class AndroidDatabaseConfig implements DatabaseConfig { private final File dbDir, keyDir; - @Nullable - private volatile SecretKey key = null; - AndroidDatabaseConfig(File dbDir, File keyDir) { this.dbDir = dbDir; this.keyDir = keyDir; @@ -62,21 +56,6 @@ class AndroidDatabaseConfig implements DatabaseConfig { return keyDir; } - @Override - public void setEncryptionKey(SecretKey key) { - LOG.info("Setting database key"); - this.key = key; - } - - @Override - @Nullable - public SecretKey getEncryptionKey() { - SecretKey key = this.key; - if (LOG.isLoggable(INFO)) - LOG.info("Database key has been set: " + (key != null)); - return key; - } - @Override public long getMaxSize() { return Long.MAX_VALUE; diff --git a/briar-android/src/main/java/org/briarproject/briar/android/controller/ConfigControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/controller/ConfigControllerImpl.java index cb0d2c3c3..1f7305371 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/controller/ConfigControllerImpl.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/controller/ConfigControllerImpl.java @@ -9,20 +9,11 @@ import org.briarproject.bramble.api.db.DatabaseConfig; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.util.AndroidUtils; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; import java.util.logging.Logger; import javax.annotation.Nullable; import javax.inject.Inject; -import static java.util.logging.Level.WARNING; -import static org.briarproject.bramble.util.LogUtils.logException; - @NotNullByDefault public class ConfigControllerImpl implements ConfigController { @@ -30,12 +21,9 @@ public class ConfigControllerImpl implements ConfigController { Logger.getLogger(ConfigControllerImpl.class.getName()); private static final String PREF_DB_KEY = "key"; - private static final String DB_KEY_FILENAME = "db.key"; - private static final String DB_KEY_BACKUP_FILENAME = "db.key.bak"; private final SharedPreferences briarPrefs; - private final File dbKeyFile, dbKeyBackupFile; - private final AccountManager accountManager; + protected final AccountManager accountManager; protected final DatabaseConfig databaseConfig; @Inject @@ -44,16 +32,13 @@ public class ConfigControllerImpl implements ConfigController { this.briarPrefs = briarPrefs; this.accountManager = accountManager; this.databaseConfig = databaseConfig; - File keyDir = databaseConfig.getDatabaseKeyDirectory(); - dbKeyFile = new File(keyDir, DB_KEY_FILENAME); - dbKeyBackupFile = new File(keyDir, DB_KEY_BACKUP_FILENAME); } @Override @Nullable public String getEncryptedDatabaseKey() { String key = getDatabaseKeyFromPreferences(); - if (key == null) key = getDatabaseKeyFromFile(); + if (key == null) key = accountManager.getEncryptedDatabaseKey(); else migrateDatabaseKeyToFile(key); return key; } @@ -66,40 +51,8 @@ public class ConfigControllerImpl implements ConfigController { return key; } - @Nullable - private String getDatabaseKeyFromFile() { - String key = readDbKeyFromFile(dbKeyFile); - if (key == null) { - LOG.info("No database key in primary file"); - key = readDbKeyFromFile(dbKeyBackupFile); - if (key == null) LOG.info("No database key in backup file"); - else LOG.warning("Found database key in backup file"); - } else { - LOG.info("Found database key in primary file"); - } - return key; - } - - @Nullable - private String readDbKeyFromFile(File f) { - if (!f.exists()) { - LOG.info("Key file does not exist"); - return null; - } - try { - BufferedReader reader = new BufferedReader(new InputStreamReader( - new FileInputStream(f), "UTF-8")); - String key = reader.readLine(); - reader.close(); - return key; - } catch (IOException e) { - logException(LOG, WARNING, e); - return null; - } - } - private void migrateDatabaseKeyToFile(String key) { - if (storeEncryptedDatabaseKey(key)) { + if (accountManager.storeEncryptedDatabaseKey(key)) { if (briarPrefs.edit().remove(PREF_DB_KEY).commit()) LOG.info("Database key migrated to file"); else LOG.warning("Database key not removed from preferences"); @@ -110,47 +63,7 @@ public class ConfigControllerImpl implements ConfigController { @Override public boolean storeEncryptedDatabaseKey(String hex) { - LOG.info("Storing database key in file"); - // Create the directory if necessary - if (databaseConfig.getDatabaseKeyDirectory().mkdirs()) - LOG.info("Created database key directory"); - // If only the backup file exists, rename it so we don't overwrite it - if (dbKeyBackupFile.exists() && !dbKeyFile.exists()) { - if (dbKeyBackupFile.renameTo(dbKeyFile)) - LOG.info("Renamed old backup"); - else LOG.warning("Failed to rename old backup"); - } - try { - // Write to the backup file - writeDbKeyToFile(hex, dbKeyBackupFile); - LOG.info("Stored database key in backup file"); - // Delete the old primary file, if it exists - if (dbKeyFile.exists()) { - if (dbKeyFile.delete()) LOG.info("Deleted primary file"); - else LOG.warning("Failed to delete primary file"); - } - // The backup file becomes the new primary - if (dbKeyBackupFile.renameTo(dbKeyFile)) { - LOG.info("Renamed backup file to primary"); - } else { - LOG.warning("Failed to rename backup file to primary"); - return false; // Don't overwrite our only copy - } - // Write a second copy to the backup file - writeDbKeyToFile(hex, dbKeyBackupFile); - LOG.info("Stored second copy of database key in backup file"); - return true; - } catch (IOException e) { - logException(LOG, WARNING, e); - return false; - } - } - - private void writeDbKeyToFile(String key, File f) throws IOException { - FileOutputStream out = new FileOutputStream(f); - out.write(key.getBytes("UTF-8")); - out.flush(); - out.close(); + return accountManager.storeEncryptedDatabaseKey(hex); } @Override diff --git a/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordControllerImpl.java index ca9634502..5a3cd5b8d 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordControllerImpl.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordControllerImpl.java @@ -57,7 +57,7 @@ public class PasswordControllerImpl extends ConfigControllerImpl if (key == null) { resultHandler.onResult(false); } else { - databaseConfig.setEncryptionKey(new SecretKey(key)); + accountManager.setDatabaseKey(new SecretKey(key)); resultHandler.onResult(true); } }); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/login/SetupControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/login/SetupControllerImpl.java index 30d039849..a2395d894 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/login/SetupControllerImpl.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/login/SetupControllerImpl.java @@ -115,7 +115,7 @@ public class SetupControllerImpl extends PasswordControllerImpl SecretKey key = crypto.generateSecretKey(); String hex = encryptDatabaseKey(key, password); storeEncryptedDatabaseKey(hex); - databaseConfig.setEncryptionKey(key); + accountManager.setDatabaseKey(key); resultHandler.onResult(null); }); } diff --git a/briar-android/src/test/java/org/briarproject/briar/android/TestDatabaseKeyUtils.java b/briar-android/src/test/java/org/briarproject/briar/android/TestDatabaseKeyUtils.java deleted file mode 100644 index 0e9173105..000000000 --- a/briar-android/src/test/java/org/briarproject/briar/android/TestDatabaseKeyUtils.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.briarproject.briar.android; - -import org.briarproject.bramble.api.nullsafety.NotNullByDefault; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; - -import javax.annotation.Nullable; - -import static junit.framework.Assert.assertTrue; - -@NotNullByDefault -public class TestDatabaseKeyUtils { - - public static void storeDatabaseKey(File f, String hex) throws IOException { - f.getParentFile().mkdirs(); - FileOutputStream out = new FileOutputStream(f); - out.write(hex.getBytes("UTF-8")); - out.flush(); - out.close(); - } - - @Nullable - public static String loadDatabaseKey(File f) throws IOException { - BufferedReader reader = new BufferedReader(new InputStreamReader( - new FileInputStream(f), "UTF-8")); - String hex = reader.readLine(); - reader.close(); - return hex; - } -} diff --git a/briar-android/src/test/java/org/briarproject/briar/android/controller/ConfigControllerImplTest.java b/briar-android/src/test/java/org/briarproject/briar/android/controller/ConfigControllerImplTest.java index d8e4445c2..06f1165ab 100644 --- a/briar-android/src/test/java/org/briarproject/briar/android/controller/ConfigControllerImplTest.java +++ b/briar-android/src/test/java/org/briarproject/briar/android/controller/ConfigControllerImplTest.java @@ -7,21 +7,11 @@ import org.briarproject.bramble.api.account.AccountManager; import org.briarproject.bramble.api.db.DatabaseConfig; import org.briarproject.bramble.test.BrambleMockTestCase; import org.jmock.Expectations; -import org.junit.After; import org.junit.Test; -import java.io.File; - import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertNull; -import static junit.framework.Assert.assertTrue; -import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory; import static org.briarproject.bramble.test.TestUtils.getRandomBytes; -import static org.briarproject.bramble.test.TestUtils.getTestDirectory; import static org.briarproject.bramble.util.StringUtils.toHexString; -import static org.briarproject.briar.android.TestDatabaseKeyUtils.loadDatabaseKey; -import static org.briarproject.briar.android.TestDatabaseKeyUtils.storeDatabaseKey; public class ConfigControllerImplTest extends BrambleMockTestCase { @@ -33,21 +23,15 @@ public class ConfigControllerImplTest extends BrambleMockTestCase { context.mock(DatabaseConfig.class); private final Editor editor = context.mock(Editor.class); - private final byte[] encryptedKey = getRandomBytes(123); - private final String encryptedKeyHex = toHexString(encryptedKey); - private final String oldEncryptedKeyHex = toHexString(getRandomBytes(123)); - private final File testDir = getTestDirectory(); - private final File keyDir = new File(testDir, "key"); - private final File keyFile = new File(keyDir, "db.key"); - private final File keyBackupFile = new File(keyDir, "db.key.bak"); + private final String encryptedKeyHex = toHexString(getRandomBytes(123)); @Test - public void testDbKeyIsMigratedFromPreferencesToFile() throws Exception { + public void testDbKeyIsMigratedFromPreferencesToFile() { context.checking(new Expectations() {{ oneOf(prefs).getString("key", null); will(returnValue(encryptedKeyHex)); - allowing(databaseConfig).getDatabaseKeyDirectory(); - will(returnValue(keyDir)); + oneOf(accountManager).storeEncryptedDatabaseKey(encryptedKeyHex); + will(returnValue(true)); oneOf(prefs).edit(); will(returnValue(editor)); oneOf(editor).remove("key"); @@ -56,153 +40,10 @@ public class ConfigControllerImplTest extends BrambleMockTestCase { will(returnValue(true)); }}); - assertFalse(keyFile.exists()); - assertFalse(keyBackupFile.exists()); - ConfigControllerImpl c = new ConfigControllerImpl(prefs, accountManager, databaseConfig); assertEquals(encryptedKeyHex, c.getEncryptedDatabaseKey()); - - assertTrue(keyFile.exists()); - assertTrue(keyBackupFile.exists()); - assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile)); - assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile)); } - @Test - public void testDbKeyIsLoadedFromPrimaryFile() throws Exception { - context.checking(new Expectations() {{ - oneOf(prefs).getString("key", null); - will(returnValue(null)); - allowing(databaseConfig).getDatabaseKeyDirectory(); - will(returnValue(keyDir)); - }}); - - assertFalse(keyFile.exists()); - assertFalse(keyBackupFile.exists()); - - storeDatabaseKey(keyFile, encryptedKeyHex); - - assertTrue(keyFile.exists()); - assertFalse(keyBackupFile.exists()); - assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile)); - - ConfigControllerImpl c = new ConfigControllerImpl(prefs, accountManager, - databaseConfig); - - assertEquals(encryptedKeyHex, c.getEncryptedDatabaseKey()); - - assertTrue(keyFile.exists()); - assertFalse(keyBackupFile.exists()); - assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile)); - } - - @Test - public void testDbKeyIsLoadedFromBackupFile() throws Exception { - context.checking(new Expectations() {{ - oneOf(prefs).getString("key", null); - will(returnValue(null)); - allowing(databaseConfig).getDatabaseKeyDirectory(); - will(returnValue(keyDir)); - }}); - - assertFalse(keyFile.exists()); - assertFalse(keyBackupFile.exists()); - - storeDatabaseKey(keyBackupFile, encryptedKeyHex); - - assertFalse(keyFile.exists()); - assertTrue(keyBackupFile.exists()); - assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile)); - - ConfigControllerImpl c = new ConfigControllerImpl(prefs, accountManager, - databaseConfig); - - assertEquals(encryptedKeyHex, c.getEncryptedDatabaseKey()); - - assertFalse(keyFile.exists()); - assertTrue(keyBackupFile.exists()); - assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile)); - } - - @Test - public void testDbKeyIsNullIfNotFound() { - context.checking(new Expectations() {{ - oneOf(prefs).getString("key", null); - will(returnValue(null)); - allowing(databaseConfig).getDatabaseKeyDirectory(); - will(returnValue(keyDir)); - }}); - - assertFalse(keyFile.exists()); - assertFalse(keyBackupFile.exists()); - - ConfigControllerImpl c = new ConfigControllerImpl(prefs, accountManager, - databaseConfig); - - assertNull(c.getEncryptedDatabaseKey()); - - assertFalse(keyFile.exists()); - assertFalse(keyBackupFile.exists()); - } - - @Test - public void testStoringDbKeyOverwritesPrimary() throws Exception { - context.checking(new Expectations() {{ - allowing(databaseConfig).getDatabaseKeyDirectory(); - will(returnValue(keyDir)); - }}); - - assertFalse(keyFile.exists()); - assertFalse(keyBackupFile.exists()); - - storeDatabaseKey(keyFile, oldEncryptedKeyHex); - - assertTrue(keyFile.exists()); - assertFalse(keyBackupFile.exists()); - assertEquals(oldEncryptedKeyHex, loadDatabaseKey(keyFile)); - - ConfigController c = new ConfigControllerImpl(prefs, accountManager, - databaseConfig); - - assertTrue(c.storeEncryptedDatabaseKey(encryptedKeyHex)); - - assertTrue(keyFile.exists()); - assertTrue(keyBackupFile.exists()); - assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile)); - assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile)); - } - - @Test - public void testStoringDbKeyOverwritesBackup() throws Exception { - context.checking(new Expectations() {{ - allowing(databaseConfig).getDatabaseKeyDirectory(); - will(returnValue(keyDir)); - }}); - - assertFalse(keyFile.exists()); - assertFalse(keyBackupFile.exists()); - - storeDatabaseKey(keyBackupFile, oldEncryptedKeyHex); - - assertFalse(keyFile.exists()); - assertTrue(keyBackupFile.exists()); - assertEquals(oldEncryptedKeyHex, loadDatabaseKey(keyBackupFile)); - - ConfigController c = new ConfigControllerImpl(prefs, accountManager, - databaseConfig); - - assertTrue(c.storeEncryptedDatabaseKey(encryptedKeyHex)); - - assertTrue(keyFile.exists()); - assertTrue(keyBackupFile.exists()); - assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile)); - assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile)); - } - - @After - public void tearDown() { - deleteTestDirectory(testDir); - } } diff --git a/briar-android/src/test/java/org/briarproject/briar/android/login/PasswordControllerImplTest.java b/briar-android/src/test/java/org/briarproject/briar/android/login/PasswordControllerImplTest.java index dcc2685b6..9c64083cd 100644 --- a/briar-android/src/test/java/org/briarproject/briar/android/login/PasswordControllerImplTest.java +++ b/briar-android/src/test/java/org/briarproject/briar/android/login/PasswordControllerImplTest.java @@ -9,23 +9,16 @@ import org.briarproject.bramble.api.db.DatabaseConfig; import org.briarproject.bramble.test.BrambleMockTestCase; import org.briarproject.bramble.test.ImmediateExecutor; import org.jmock.Expectations; -import org.junit.After; import org.junit.Test; -import java.io.File; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicBoolean; -import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; -import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory; import static org.briarproject.bramble.test.TestUtils.getRandomBytes; import static org.briarproject.bramble.test.TestUtils.getSecretKey; -import static org.briarproject.bramble.test.TestUtils.getTestDirectory; import static org.briarproject.bramble.util.StringUtils.toHexString; -import static org.briarproject.briar.android.TestDatabaseKeyUtils.loadDatabaseKey; -import static org.briarproject.briar.android.TestDatabaseKeyUtils.storeDatabaseKey; public class PasswordControllerImplTest extends BrambleMockTestCase { @@ -46,32 +39,27 @@ public class PasswordControllerImplTest extends BrambleMockTestCase { private final byte[] oldEncryptedKey = getRandomBytes(123); private final byte[] newEncryptedKey = getRandomBytes(123); private final byte[] key = getSecretKey().getBytes(); - private final File testDir = getTestDirectory(); - private final File keyDir = new File(testDir, "key"); - private final File keyFile = new File(keyDir, "db.key"); - private final File keyBackupFile = new File(keyDir, "db.key.bak"); + private final String oldEncryptedKeyHex = toHexString(oldEncryptedKey); + private final String newEncryptedKeyHex = toHexString(newEncryptedKey); @Test - public void testChangePasswordReturnsTrue() throws Exception { + public void testChangePasswordReturnsTrue() { context.checking(new Expectations() {{ // Look up the encrypted DB key oneOf(briarPrefs).getString("key", null); will(returnValue(null)); - allowing(databaseConfig).getDatabaseKeyDirectory(); - will(returnValue(keyDir)); + oneOf(accountManager).getEncryptedDatabaseKey(); + will(returnValue(oldEncryptedKeyHex)); // Decrypt and re-encrypt the key oneOf(crypto).decryptWithPassword(oldEncryptedKey, oldPassword); will(returnValue(key)); oneOf(crypto).encryptWithPassword(key, newPassword); will(returnValue(newEncryptedKey)); + // Store the new key + oneOf(accountManager).storeEncryptedDatabaseKey(newEncryptedKeyHex); + will(returnValue(true)); }}); - assertFalse(keyFile.exists()); - assertFalse(keyBackupFile.exists()); - - storeDatabaseKey(keyFile, toHexString(oldEncryptedKey)); - storeDatabaseKey(keyBackupFile, toHexString(oldEncryptedKey)); - PasswordControllerImpl p = new PasswordControllerImpl(briarPrefs, accountManager, databaseConfig, cryptoExecutor, crypto, estimator); @@ -79,34 +67,21 @@ public class PasswordControllerImplTest extends BrambleMockTestCase { AtomicBoolean capturedResult = new AtomicBoolean(false); p.changePassword(oldPassword, newPassword, capturedResult::set); assertTrue(capturedResult.get()); - - assertTrue(keyFile.exists()); - assertTrue(keyBackupFile.exists()); - assertEquals(toHexString(newEncryptedKey), loadDatabaseKey(keyFile)); - assertEquals(toHexString(newEncryptedKey), - loadDatabaseKey(keyBackupFile)); } @Test - public void testChangePasswordReturnsFalseIfOldPasswordIsWrong() - throws Exception { + public void testChangePasswordReturnsFalseIfOldPasswordIsWrong() { context.checking(new Expectations() {{ // Look up the encrypted DB key oneOf(briarPrefs).getString("key", null); will(returnValue(null)); - allowing(databaseConfig).getDatabaseKeyDirectory(); - will(returnValue(keyDir)); + oneOf(accountManager).getEncryptedDatabaseKey(); + will(returnValue(oldEncryptedKeyHex)); // Try to decrypt the key - the password is wrong oneOf(crypto).decryptWithPassword(oldEncryptedKey, oldPassword); will(returnValue(null)); }}); - assertFalse(keyFile.exists()); - assertFalse(keyBackupFile.exists()); - - storeDatabaseKey(keyFile, toHexString(oldEncryptedKey)); - storeDatabaseKey(keyBackupFile, toHexString(oldEncryptedKey)); - PasswordControllerImpl p = new PasswordControllerImpl(briarPrefs, accountManager, databaseConfig, cryptoExecutor, crypto, estimator); @@ -114,16 +89,5 @@ public class PasswordControllerImplTest extends BrambleMockTestCase { AtomicBoolean capturedResult = new AtomicBoolean(true); p.changePassword(oldPassword, newPassword, capturedResult::set); assertFalse(capturedResult.get()); - - assertTrue(keyFile.exists()); - assertTrue(keyBackupFile.exists()); - assertEquals(toHexString(oldEncryptedKey), loadDatabaseKey(keyFile)); - assertEquals(toHexString(oldEncryptedKey), - loadDatabaseKey(keyBackupFile)); - } - - @After - public void tearDown() { - deleteTestDirectory(testDir); } } diff --git a/briar-android/src/test/java/org/briarproject/briar/android/login/SetupControllerImplTest.java b/briar-android/src/test/java/org/briarproject/briar/android/login/SetupControllerImplTest.java index dd8825147..4671bb1c4 100644 --- a/briar-android/src/test/java/org/briarproject/briar/android/login/SetupControllerImplTest.java +++ b/briar-android/src/test/java/org/briarproject/briar/android/login/SetupControllerImplTest.java @@ -1,7 +1,6 @@ package org.briarproject.briar.android.login; import android.content.SharedPreferences; -import android.content.pm.ApplicationInfo; import org.briarproject.bramble.api.account.AccountManager; import org.briarproject.bramble.api.crypto.CryptoComponent; @@ -14,25 +13,18 @@ import org.briarproject.bramble.test.BrambleMockTestCase; import org.briarproject.bramble.test.ImmediateExecutor; import org.jmock.Expectations; import org.jmock.lib.legacy.ClassImposteriser; -import org.junit.After; import org.junit.Test; -import java.io.File; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicBoolean; -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertTrue; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH; -import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory; import static org.briarproject.bramble.test.TestUtils.getLocalAuthor; import static org.briarproject.bramble.test.TestUtils.getRandomBytes; import static org.briarproject.bramble.test.TestUtils.getSecretKey; -import static org.briarproject.bramble.test.TestUtils.getTestDirectory; import static org.briarproject.bramble.util.StringUtils.getRandomString; import static org.briarproject.bramble.util.StringUtils.toHexString; -import static org.briarproject.briar.android.TestDatabaseKeyUtils.loadDatabaseKey; public class SetupControllerImplTest extends BrambleMockTestCase { @@ -55,11 +47,8 @@ public class SetupControllerImplTest extends BrambleMockTestCase { private final String password = "some.strong.pass"; private final LocalAuthor localAuthor = getLocalAuthor(); private final byte[] encryptedKey = getRandomBytes(123); + private final String encryptedKeyHex = toHexString(encryptedKey); private final SecretKey key = getSecretKey(); - private final File testDir = getTestDirectory(); - private final File keyDir = new File(testDir, "key"); - private final File keyFile = new File(keyDir, "db.key"); - private final File keyBackupFile = new File(keyDir, "db.key.bak"); public SetupControllerImplTest() { context.setImposteriser(ClassImposteriser.INSTANCE); @@ -68,13 +57,8 @@ public class SetupControllerImplTest extends BrambleMockTestCase { @Test @SuppressWarnings("ResultOfMethodCallIgnored") - public void testCreateAccount() throws Exception { + public void testCreateAccount() { context.checking(new Expectations() {{ - // Allow the contents of the data directory to be logged - allowing(setupActivity).getApplicationInfo(); - will(returnValue(new ApplicationInfo() {{ - dataDir = testDir.getAbsolutePath(); - }})); // Set the author name and password oneOf(setupActivity).setAuthorName(authorName); oneOf(setupActivity).setPassword(password); @@ -94,15 +78,12 @@ public class SetupControllerImplTest extends BrambleMockTestCase { oneOf(crypto).encryptWithPassword(key.getBytes(), password); will(returnValue(encryptedKey)); // Store the encrypted key - allowing(databaseConfig).getDatabaseKeyDirectory(); - will(returnValue(keyDir)); - // Attach the database key to the database config - oneOf(databaseConfig).setEncryptionKey(key); + oneOf(accountManager).storeEncryptedDatabaseKey(encryptedKeyHex); + will(returnValue(true)); + // Pass the database key to the account manager + oneOf(accountManager).setDatabaseKey(key); }}); - assertFalse(keyFile.exists()); - assertFalse(keyBackupFile.exists()); - SetupControllerImpl s = new SetupControllerImpl(briarPrefs, accountManager, databaseConfig, cryptoExecutor, crypto, estimator, identityManager); @@ -113,17 +94,5 @@ public class SetupControllerImplTest extends BrambleMockTestCase { s.setPassword(password); s.createAccount(result -> called.set(true)); assertTrue(called.get()); - - assertTrue(keyFile.exists()); - assertTrue(keyBackupFile.exists()); - assertEquals(toHexString(encryptedKey), - loadDatabaseKey(keyFile)); - assertEquals(toHexString(encryptedKey), - loadDatabaseKey(keyBackupFile)); - } - - @After - public void tearDown() { - deleteTestDirectory(testDir); } } diff --git a/briar-core/src/test/java/org/briarproject/briar/feed/FeedManagerIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/feed/FeedManagerIntegrationTest.java index fec963b33..7aafa6ce4 100644 --- a/briar-core/src/test/java/org/briarproject/briar/feed/FeedManagerIntegrationTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/feed/FeedManagerIntegrationTest.java @@ -27,6 +27,7 @@ import org.junit.Test; import java.io.File; import java.util.Collection; +import static org.briarproject.bramble.test.TestUtils.getSecretKey; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -53,6 +54,8 @@ public class FeedManagerIntegrationTest extends BriarTestCase { LocalAuthor localAuthor = identityManager.createLocalAuthor("feedTest"); identityManager.registerLocalAuthor(localAuthor); + component.getAccountManager().setDatabaseKey(getSecretKey()); + lifecycleManager = component.getLifecycleManager(); lifecycleManager.startServices(); lifecycleManager.waitForStartup(); diff --git a/briar-core/src/test/java/org/briarproject/briar/feed/FeedManagerIntegrationTestComponent.java b/briar-core/src/test/java/org/briarproject/briar/feed/FeedManagerIntegrationTestComponent.java index 685eedacb..3fc4a9ea6 100644 --- a/briar-core/src/test/java/org/briarproject/briar/feed/FeedManagerIntegrationTestComponent.java +++ b/briar-core/src/test/java/org/briarproject/briar/feed/FeedManagerIntegrationTestComponent.java @@ -1,5 +1,7 @@ package org.briarproject.briar.feed; +import org.briarproject.bramble.account.AccountModule; +import org.briarproject.bramble.api.account.AccountManager; import org.briarproject.bramble.api.identity.IdentityManager; import org.briarproject.bramble.api.lifecycle.LifecycleManager; import org.briarproject.bramble.client.ClientModule; @@ -36,6 +38,7 @@ import dagger.Component; TestSecureRandomModule.class, TestSocksModule.class, TestDnsModule.class, + AccountModule.class, BriarClientModule.class, ClientModule.class, ContactModule.class, @@ -79,6 +82,8 @@ interface FeedManagerIntegrationTestComponent { IdentityManager getIdentityManager(); + AccountManager getAccountManager(); + LifecycleManager getLifecycleManager(); FeedManager getFeedManager(); diff --git a/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTestComponent.java b/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTestComponent.java index 108f48849..2da286b05 100644 --- a/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTestComponent.java +++ b/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTestComponent.java @@ -1,5 +1,6 @@ package org.briarproject.briar.introduction; +import org.briarproject.bramble.account.AccountModule; import org.briarproject.bramble.client.ClientModule; import org.briarproject.bramble.contact.ContactModule; import org.briarproject.bramble.crypto.CryptoExecutorModule; @@ -36,6 +37,7 @@ import dagger.Component; TestDatabaseModule.class, TestPluginConfigModule.class, TestSecureRandomModule.class, + AccountModule.class, BlogModule.class, BriarClientModule.class, ClientModule.class, diff --git a/briar-core/src/test/java/org/briarproject/briar/messaging/SimplexMessagingIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/messaging/SimplexMessagingIntegrationTest.java index 5c8b0ca65..c846c1c73 100644 --- a/briar-core/src/test/java/org/briarproject/briar/messaging/SimplexMessagingIntegrationTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/messaging/SimplexMessagingIntegrationTest.java @@ -100,6 +100,8 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase { private ContactId setUp(SimplexMessagingIntegrationTestComponent device, LocalAuthor local, Author remote, boolean alice) throws Exception { + // Create a database key + device.getAccountManager().setDatabaseKey(getSecretKey()); // Add an identity for the user IdentityManager identityManager = device.getIdentityManager(); identityManager.registerLocalAuthor(local); diff --git a/briar-core/src/test/java/org/briarproject/briar/messaging/SimplexMessagingIntegrationTestComponent.java b/briar-core/src/test/java/org/briarproject/briar/messaging/SimplexMessagingIntegrationTestComponent.java index 7dade1ed1..a5f9d9bc6 100644 --- a/briar-core/src/test/java/org/briarproject/briar/messaging/SimplexMessagingIntegrationTestComponent.java +++ b/briar-core/src/test/java/org/briarproject/briar/messaging/SimplexMessagingIntegrationTestComponent.java @@ -1,5 +1,7 @@ package org.briarproject.briar.messaging; +import org.briarproject.bramble.account.AccountModule; +import org.briarproject.bramble.api.account.AccountManager; import org.briarproject.bramble.api.contact.ContactManager; import org.briarproject.bramble.api.event.EventBus; import org.briarproject.bramble.api.identity.IdentityManager; @@ -39,6 +41,7 @@ import dagger.Component; TestDatabaseModule.class, TestPluginConfigModule.class, TestSecureRandomModule.class, + AccountModule.class, BriarClientModule.class, ClientModule.class, ContactModule.class, @@ -77,6 +80,8 @@ interface SimplexMessagingIntegrationTestComponent { IdentityManager getIdentityManager(); + AccountManager getAccountManager(); + ContactManager getContactManager(); MessagingManager getMessagingManager(); diff --git a/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTest.java index 9f2ecec4a..0e30fa848 100644 --- a/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTest.java @@ -140,6 +140,9 @@ public abstract class BriarIntegrationTest