properly handle stage 2: key exists, but e2e is not setup on this device

Signed-off-by: tobiasKaminsky <tobias@kaminsky.me>
This commit is contained in:
tobiasKaminsky 2022-11-18 11:47:55 +01:00
parent 1b945b6131
commit e3a7453846
No known key found for this signature in database
GPG key ID: 0E00D4D47D0C5AF7
9 changed files with 1223 additions and 48 deletions

View file

@ -2,7 +2,7 @@
"formatVersion": 1, "formatVersion": 1,
"database": { "database": {
"version": 65, "version": 65,
"identityHash": "1aa68e80a3cb0006ef54981abad692a9", "identityHash": "97be4a2bf1d8d2a4db027a996a823010",
"entities": [ "entities": [
{ {
"tableName": "arbitrary_data", "tableName": "arbitrary_data",
@ -44,7 +44,7 @@
}, },
{ {
"tableName": "capabilities", "tableName": "capabilities",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `account` TEXT, `version_mayor` INTEGER, `version_minor` INTEGER, `version_micro` INTEGER, `version_string` TEXT, `version_edition` TEXT, `extended_support` INTEGER, `core_pollinterval` INTEGER, `sharing_api_enabled` INTEGER, `sharing_public_enabled` INTEGER, `sharing_public_password_enforced` INTEGER, `sharing_public_expire_date_enabled` INTEGER, `sharing_public_expire_date_days` INTEGER, `sharing_public_expire_date_enforced` INTEGER, `sharing_public_send_mail` INTEGER, `sharing_public_upload` INTEGER, `sharing_user_send_mail` INTEGER, `sharing_resharing` INTEGER, `sharing_federation_outgoing` INTEGER, `sharing_federation_incoming` INTEGER, `files_bigfilechunking` INTEGER, `files_undelete` INTEGER, `files_versioning` INTEGER, `external_links` INTEGER, `server_name` TEXT, `server_color` TEXT, `server_text_color` TEXT, `server_element_color` TEXT, `server_slogan` TEXT, `server_logo` TEXT, `background_url` TEXT, `end_to_end_encryption` INTEGER, `activity` INTEGER, `background_default` INTEGER, `background_plain` INTEGER, `richdocument` INTEGER, `richdocument_mimetype_list` TEXT, `richdocument_direct_editing` INTEGER, `richdocument_direct_templates` INTEGER, `richdocument_optional_mimetype_list` TEXT, `sharing_public_ask_for_optional_password` INTEGER, `richdocument_product_name` TEXT, `direct_editing_etag` TEXT, `user_status` INTEGER, `user_status_supports_emoji` INTEGER, `etag` TEXT, `files_locking_version` TEXT)", "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`_id` INTEGER PRIMARY KEY AUTOINCREMENT, `account` TEXT, `version_mayor` INTEGER, `version_minor` INTEGER, `version_micro` INTEGER, `version_string` TEXT, `version_edition` TEXT, `extended_support` INTEGER, `core_pollinterval` INTEGER, `sharing_api_enabled` INTEGER, `sharing_public_enabled` INTEGER, `sharing_public_password_enforced` INTEGER, `sharing_public_expire_date_enabled` INTEGER, `sharing_public_expire_date_days` INTEGER, `sharing_public_expire_date_enforced` INTEGER, `sharing_public_send_mail` INTEGER, `sharing_public_upload` INTEGER, `sharing_user_send_mail` INTEGER, `sharing_resharing` INTEGER, `sharing_federation_outgoing` INTEGER, `sharing_federation_incoming` INTEGER, `files_bigfilechunking` INTEGER, `files_undelete` INTEGER, `files_versioning` INTEGER, `external_links` INTEGER, `server_name` TEXT, `server_color` TEXT, `server_text_color` TEXT, `server_element_color` TEXT, `server_slogan` TEXT, `server_logo` TEXT, `background_url` TEXT, `end_to_end_encryption` INTEGER, `end_to_end_encryption_keys_exist` INTEGER, `activity` INTEGER, `background_default` INTEGER, `background_plain` INTEGER, `richdocument` INTEGER, `richdocument_mimetype_list` TEXT, `richdocument_direct_editing` INTEGER, `richdocument_direct_templates` INTEGER, `richdocument_optional_mimetype_list` TEXT, `sharing_public_ask_for_optional_password` INTEGER, `richdocument_product_name` TEXT, `direct_editing_etag` TEXT, `user_status` INTEGER, `user_status_supports_emoji` INTEGER, `etag` TEXT, `files_locking_version` TEXT)",
"fields": [ "fields": [
{ {
"fieldPath": "id", "fieldPath": "id",
@ -244,6 +244,12 @@
"affinity": "INTEGER", "affinity": "INTEGER",
"notNull": false "notNull": false
}, },
{
"fieldPath": "endToEndEncryptionKeysExist",
"columnName": "end_to_end_encryption_keys_exist",
"affinity": "INTEGER",
"notNull": false
},
{ {
"fieldPath": "activity", "fieldPath": "activity",
"columnName": "activity", "columnName": "activity",
@ -1112,7 +1118,7 @@
"views": [], "views": [],
"setupQueries": [ "setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '1aa68e80a3cb0006ef54981abad692a9')" "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '97be4a2bf1d8d2a4db027a996a823010')"
] ]
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -96,6 +96,8 @@ data class CapabilityEntity(
val serverBackgroundUrl: String?, val serverBackgroundUrl: String?,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_END_TO_END_ENCRYPTION) @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_END_TO_END_ENCRYPTION)
val endToEndEncryption: Int?, val endToEndEncryption: Int?,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_END_TO_END_ENCRYPTION_KEYS_EXIST)
val endToEndEncryptionKeysExist: Int?,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_ACTIVITY) @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_ACTIVITY)
val activity: Int?, val activity: Int?,
@ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_DEFAULT) @ColumnInfo(name = ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_DEFAULT)

View file

@ -1971,6 +1971,8 @@ public class FileDataStorageManager {
capability.getServerLogo()); capability.getServerLogo());
contentValues.put(ProviderTableMeta.CAPABILITIES_END_TO_END_ENCRYPTION, contentValues.put(ProviderTableMeta.CAPABILITIES_END_TO_END_ENCRYPTION,
capability.getEndToEndEncryption().getValue()); capability.getEndToEndEncryption().getValue());
contentValues.put(ProviderTableMeta.CAPABILITIES_END_TO_END_ENCRYPTION_KEYS_EXIST,
capability.getEndToEndEncryptionKeysExist().getValue());
contentValues.put(ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_DEFAULT, contentValues.put(ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_DEFAULT,
capability.getServerBackgroundDefault().getValue()); capability.getServerBackgroundDefault().getValue());
contentValues.put(ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_PLAIN, contentValues.put(ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_PLAIN,
@ -2117,6 +2119,10 @@ public class FileDataStorageManager {
capability.setServerSlogan(getString(cursor, ProviderTableMeta.CAPABILITIES_SERVER_SLOGAN)); capability.setServerSlogan(getString(cursor, ProviderTableMeta.CAPABILITIES_SERVER_SLOGAN));
capability.setServerLogo(getString(cursor, ProviderTableMeta.CAPABILITIES_SERVER_LOGO)); capability.setServerLogo(getString(cursor, ProviderTableMeta.CAPABILITIES_SERVER_LOGO));
capability.setEndToEndEncryption(getBoolean(cursor, ProviderTableMeta.CAPABILITIES_END_TO_END_ENCRYPTION)); capability.setEndToEndEncryption(getBoolean(cursor, ProviderTableMeta.CAPABILITIES_END_TO_END_ENCRYPTION));
capability.setEndToEndEncryptionKeysExist(
getBoolean(cursor,
ProviderTableMeta.CAPABILITIES_END_TO_END_ENCRYPTION_KEYS_EXIST)
);
capability.setServerBackgroundDefault( capability.setServerBackgroundDefault(
getBoolean(cursor, ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_DEFAULT)); getBoolean(cursor, ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_DEFAULT));
capability.setServerBackgroundPlain(getBoolean(cursor, capability.setServerBackgroundPlain(getBoolean(cursor,

View file

@ -35,7 +35,7 @@ import java.util.List;
*/ */
public class ProviderMeta { public class ProviderMeta {
public static final String DB_NAME = "filelist"; public static final String DB_NAME = "filelist";
public static final int DB_VERSION = 65; public static final int DB_VERSION = 66;
private ProviderMeta() { private ProviderMeta() {
// No instance // No instance
@ -237,6 +237,7 @@ public class ProviderMeta {
public static final String CAPABILITIES_SERVER_BACKGROUND_DEFAULT = "background_default"; public static final String CAPABILITIES_SERVER_BACKGROUND_DEFAULT = "background_default";
public static final String CAPABILITIES_SERVER_BACKGROUND_PLAIN = "background_plain"; public static final String CAPABILITIES_SERVER_BACKGROUND_PLAIN = "background_plain";
public static final String CAPABILITIES_END_TO_END_ENCRYPTION = "end_to_end_encryption"; public static final String CAPABILITIES_END_TO_END_ENCRYPTION = "end_to_end_encryption";
public static final String CAPABILITIES_END_TO_END_ENCRYPTION_KEYS_EXIST = "end_to_end_encryption_keys_exist";
public static final String CAPABILITIES_ACTIVITY = "activity"; public static final String CAPABILITIES_ACTIVITY = "activity";
public static final String CAPABILITIES_RICHDOCUMENT = "richdocument"; public static final String CAPABILITIES_RICHDOCUMENT = "richdocument";
public static final String CAPABILITIES_RICHDOCUMENT_MIMETYPE_LIST = "richdocument_mimetype_list"; public static final String CAPABILITIES_RICHDOCUMENT_MIMETYPE_LIST = "richdocument_mimetype_list";

View file

@ -78,6 +78,7 @@ import com.owncloud.android.utils.DeviceCredentialUtils;
import com.owncloud.android.utils.DisplayUtils; import com.owncloud.android.utils.DisplayUtils;
import com.owncloud.android.utils.EncryptionUtils; import com.owncloud.android.utils.EncryptionUtils;
import com.owncloud.android.utils.MimeTypeUtil; import com.owncloud.android.utils.MimeTypeUtil;
import com.owncloud.android.utils.theme.CapabilityUtils;
import com.owncloud.android.utils.theme.ViewThemeUtils; import com.owncloud.android.utils.theme.ViewThemeUtils;
import java.util.ArrayList; import java.util.ArrayList;
@ -121,6 +122,7 @@ public class SettingsActivity extends PreferenceActivity
private static final int ACTION_CONFIRM_DEVICE_CREDENTIALS = 7; private static final int ACTION_CONFIRM_DEVICE_CREDENTIALS = 7;
private static final int ACTION_REQUEST_CODE_DAVDROID_SETUP = 10; private static final int ACTION_REQUEST_CODE_DAVDROID_SETUP = 10;
private static final int ACTION_SHOW_MNEMONIC = 11; private static final int ACTION_SHOW_MNEMONIC = 11;
private static final int ACTION_E2E = 12;
private static final int TRUE_VALUE = 1; private static final int TRUE_VALUE = 1;
private static final String DAV_PATH = "/remote.php/dav"; private static final String DAV_PATH = "/remote.php/dav";
@ -328,6 +330,8 @@ public class SettingsActivity extends PreferenceActivity
setupE2EPreference(preferenceCategoryMore); setupE2EPreference(preferenceCategoryMore);
setupE2EKeysExist(preferenceCategoryMore);
setupE2EMnemonicPreference(preferenceCategoryMore); setupE2EMnemonicPreference(preferenceCategoryMore);
removeE2E(preferenceCategoryMore); removeE2E(preferenceCategoryMore);
@ -422,14 +426,34 @@ public class SettingsActivity extends PreferenceActivity
Preference preference = findPreference("setup_e2e"); Preference preference = findPreference("setup_e2e");
if (preference != null) { if (preference != null) {
if (FileOperationsHelper.isEndToEndEncryptionSetup(this, user)) { if (FileOperationsHelper.isEndToEndEncryptionSetup(this, user) ||
!CapabilityUtils.getCapability(this).getEndToEndEncryptionKeysExist().isFalse()) {
preferenceCategoryMore.removePreference(preference); preferenceCategoryMore.removePreference(preference);
} else { } else {
preference.setOnPreferenceClickListener(p -> { preference.setOnPreferenceClickListener(p -> {
Intent i = new Intent(MainApp.getAppContext(), SetupEncryptionActivity.class); Intent i = new Intent(MainApp.getAppContext(), SetupEncryptionActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); i.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
i.putExtra("EXTRA_USER", user); i.putExtra("EXTRA_USER", user);
startActivityForResult(i, ACTION_SHOW_MNEMONIC); startActivityForResult(i, ACTION_E2E);
return true;
});
}
}
}
private void setupE2EKeysExist(PreferenceCategory preferenceCategoryMore) {
Preference preference = findPreference("setup_e2e_keys_exist");
if (preference != null) {
if (!CapabilityUtils.getCapability(this).getEndToEndEncryptionKeysExist().isTrue()) {
preferenceCategoryMore.removePreference(preference);
} else {
preference.setOnPreferenceClickListener(p -> {
Intent i = new Intent(MainApp.getAppContext(), SetupEncryptionActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
i.putExtra("EXTRA_USER", user);
startActivityForResult(i, ACTION_E2E);
return true; return true;
}); });
@ -917,6 +941,13 @@ public class SettingsActivity extends PreferenceActivity
} }
} else if (requestCode == ACTION_SHOW_MNEMONIC && resultCode == RESULT_OK) { } else if (requestCode == ACTION_SHOW_MNEMONIC && resultCode == RESULT_OK) {
handleMnemonicRequest(data); handleMnemonicRequest(data);
} else if (requestCode == ACTION_E2E) {
PreferenceCategory preferenceCategoryMore = (PreferenceCategory) findPreference("more");
setupE2EPreference(preferenceCategoryMore);
setupE2EKeysExist(preferenceCategoryMore);
setupE2EMnemonicPreference(preferenceCategoryMore);
removeE2E(preferenceCategoryMore);
} }
} }

View file

@ -1066,4 +1066,5 @@
<string name="remove_e2e_message">You can remove end to end encryption locally on this client. The encrypted files will remain on server, but will not be synced to this computer any longer.</string> <string name="remove_e2e_message">You can remove end to end encryption locally on this client. The encrypted files will remain on server, but will not be synced to this computer any longer.</string>
<string name="setup_e2e">During setup of end to end encryption, you will receive a random 12 word mnemonic, which you will need to open your files on other devices. This will only be stored on this device, and can be shown again in this screen. Please note it down in a secure place!</string> <string name="setup_e2e">During setup of end to end encryption, you will receive a random 12 word mnemonic, which you will need to open your files on other devices. This will only be stored on this device, and can be shown again in this screen. Please note it down in a secure place!</string>
<string name="error_showing_encryption_dialog">Error showing setup encryption dialog!</string> <string name="error_showing_encryption_dialog">Error showing setup encryption dialog!</string>
<string name="prefs_keys_exist">Add end to end encryption to this client</string>
</resources> </resources>

View file

@ -78,6 +78,10 @@
android:title="@string/prefs_setup_e2e" android:title="@string/prefs_setup_e2e"
android:key="setup_e2e" android:key="setup_e2e"
android:summary="@string/setup_e2e" /> android:summary="@string/setup_e2e" />
<Preference
android:title="@string/prefs_keys_exist"
android:key="setup_e2e_keys_exist"
android:summary="End to end encryption was already set up on another client. Please enter your mnemonic to allow this client to sync and decrypt the files." />
<Preference <Preference
android:title="@string/prefs_e2e_active" android:title="@string/prefs_e2e_active"
android:key="mnemonic" android:key="mnemonic"

View file

@ -6,7 +6,7 @@ buildscript {
daggerVersion = "2.44.2" daggerVersion = "2.44.2"
markwonVersion = "4.6.2" markwonVersion = "4.6.2"
prismVersion = "2.0.0" prismVersion = "2.0.0"
androidLibraryVersion = "master-SNAPSHOT" androidLibraryVersion = "e2eKey-SNAPSHOT"
mockitoVersion = "4.9.0" mockitoVersion = "4.9.0"
mockitoKotlinVersion = "4.0.0" mockitoKotlinVersion = "4.0.0"
mockkVersion = "1.13.2" mockkVersion = "1.13.2"