add cipher migration for version 4 of sqlcipher

Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
This commit is contained in:
Andy Scherzinger 2022-06-18 13:46:43 +02:00
parent a7751124a1
commit 08f5274af9
No known key found for this signature in database
GPG Key ID: 6CADC7E3523C308B
4 changed files with 80 additions and 13 deletions

View File

@ -1,6 +1,5 @@
/*
*
* Nextcloud Talk application
* Nextcloud Talk application
*
* @author Marcel Hibbe
* @author Andy Scherzinger
@ -9,18 +8,18 @@
* Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
* Copyright (C) 2017 Mario Danic <mario@lovelyhq.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* at your option) any later version.
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.nextcloud.talk.application
@ -51,6 +50,7 @@ import com.facebook.cache.disk.DiskCacheConfig
import com.facebook.drawee.backends.pipeline.Fresco
import com.facebook.imagepipeline.core.ImagePipelineConfig
import com.nextcloud.talk.BuildConfig
import com.nextcloud.talk.R
import com.nextcloud.talk.components.filebrowser.webdav.DavUtils
import com.nextcloud.talk.dagger.modules.BusModule
import com.nextcloud.talk.dagger.modules.ContextModule
@ -61,6 +61,7 @@ import com.nextcloud.talk.dagger.modules.ViewModelModule
import com.nextcloud.talk.jobs.AccountRemovalWorker
import com.nextcloud.talk.jobs.CapabilitiesWorker
import com.nextcloud.talk.jobs.SignalingSettingsWorker
import com.nextcloud.talk.models.database.Models
import com.nextcloud.talk.utils.ClosedInterfaceImpl
import com.nextcloud.talk.utils.DeviceUtils
import com.nextcloud.talk.utils.DisplayUtils
@ -74,12 +75,17 @@ import com.vanniktech.emoji.EmojiManager
import com.vanniktech.emoji.google.GoogleEmojiProvider
import de.cotech.hw.SecurityKeyManager
import de.cotech.hw.SecurityKeyManagerConfig
import io.requery.android.sqlcipher.SqlCipherDatabaseSource
import net.sqlcipher.database.SQLiteDatabase
import net.sqlcipher.database.SQLiteDatabaseHook
import net.sqlcipher.database.SQLiteOpenHelper
import okhttp3.OkHttpClient
import org.conscrypt.Conscrypt
import org.webrtc.PeerConnectionFactory
import org.webrtc.voiceengine.WebRtcAudioManager
import org.webrtc.voiceengine.WebRtcAudioUtils
import java.security.Security
import java.util.Locale
import java.util.concurrent.TimeUnit
import javax.inject.Inject
import javax.inject.Singleton
@ -113,6 +119,17 @@ class NextcloudTalkApplication : MultiDexApplication(), LifecycleObserver {
lateinit var okHttpClient: OkHttpClient
//endregion
val hook: SQLiteDatabaseHook = object : SQLiteDatabaseHook {
override fun preKey(database: SQLiteDatabase) {
// unused atm
}
override fun postKey(database: SQLiteDatabase) {
Log.i("TalkApplication", "DB cipher_migrate START")
database.rawExecSQL("PRAGMA cipher_migrate;")
Log.i("TalkApplication", "DB cipher_migrate END")
}
}
//region private methods
private fun initializeWebRtc() {
try {
@ -153,6 +170,8 @@ class NextcloudTalkApplication : MultiDexApplication(), LifecycleObserver {
componentApplication.inject(this)
checkAndUpgradeDbCypher()
Coil.setImageLoader(buildDefaultImageLoader())
setAppTheme(appPreferences.theme)
super.onCreate()
@ -241,10 +260,48 @@ class NextcloudTalkApplication : MultiDexApplication(), LifecycleObserver {
.build()
}
private fun checkAndUpgradeDbCypher() {
if (appPreferences.isDbCypherToUpgrade) {
val database = object : SqlCipherDatabaseSource(
this,
Models.DEFAULT,
this.resources.getString(R.string.nc_app_product_name).lowercase(Locale.getDefault())
.replace(" ", "_").trim { it <= ' ' } + ".sqlite",
this.getString(R.string.nc_talk_database_encryption_key),
DatabaseModule.DB_VERSION
) {
override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
checkAndUpdateCipherMigrationStatus(newVersion, appPreferences)
super.onUpgrade(db, oldVersion, newVersion)
}
}
try {
val field = SQLiteOpenHelper::class.java.getDeclaredField("mHook")
field.isAccessible = true
field.set(database, hook)
} catch (e: NoSuchFieldException) {
Log.e("SqlCipherDatabaseSource", "Error accessing mHook field")
} catch (e: IllegalAccessException) {
Log.e("SqlCipherDatabaseSource", "Error setting mHook field")
}
checkAndUpdateCipherMigrationStatus(database.writableDatabase.version, appPreferences)
}
}
private fun checkAndUpdateCipherMigrationStatus(version: Int, appPreferences: AppPreferences) {
if (version >= CIPHER_V4_MIGRATION && appPreferences.isDbCypherToUpgrade) {
appPreferences.isDbCypherToUpgrade = false
}
}
companion object {
private val TAG = NextcloudTalkApplication::class.java.simpleName
const val FIFTY_PERCENT = 0.5
const val HALF_DAY: Long = 12
const val CIPHER_V4_MIGRATION: Int = 7
//region Singleton
//endregion

View File

@ -39,6 +39,7 @@ import javax.inject.Singleton;
@Module
public class DatabaseModule {
public static final int DB_VERSION = 7;
@Provides
@Singleton
@ -46,7 +47,7 @@ public class DatabaseModule {
return new SqlCipherDatabaseSource(context, Models.DEFAULT,
context.getResources().getString(R.string.nc_app_product_name).toLowerCase()
.replace(" ", "_").trim() + ".sqlite",
context.getString(R.string.nc_talk_database_encryption_key), 6);
context.getString(R.string.nc_talk_database_encryption_key), DB_VERSION);
}
@Provides

View File

@ -281,6 +281,13 @@ public interface AppPreferences {
@KeyByResource(R.string.nc_settings_theme_key)
@UnregisterChangeListenerMethod
void unregisterThemeChangeListener(OnPreferenceValueChangedListener<String> listener);
@KeyByResource(R.string.nc_settings_db_cypher_v4_upgrade_key)
@DefaultValue(R.bool.value_true)
boolean getIsDbCypherToUpgrade();
@KeyByResource(R.string.nc_settings_db_cypher_v4_upgrade_key)
void setIsDbCypherToUpgrade(boolean value);
@KeyByResource(R.string.nc_settings_phone_book_integration_key)
@RegisterChangeListenerMethod

View File

@ -533,4 +533,6 @@
<string name="send_without_notification">Send without notification</string>
<string name="call_without_notification">Call without notification</string>
<string name="nc_settings_db_cypher_v4_upgrade_key" translatable="false">db_cypher_v4_upgrade</string>
</resources>