sql: do not reset our database if backup cannot be decrypted

This commit is contained in:
link2xt
2022-06-03 22:18:58 +00:00
parent ce47942ba3
commit 558850e68f
3 changed files with 27 additions and 6 deletions

View File

@@ -5,6 +5,7 @@
## Changes
## Fixes
- do not reset our database if imported backup cannot be decrypted #3397
## 1.85.0

View File

@@ -931,6 +931,17 @@ mod tests {
// import to context2
let backup = has_backup(&context2, backup_dir.path().as_ref()).await?;
// Import of unencrypted backup with incorrect "foobar" backup passphrase fails.
assert!(imex(
&context2,
ImexMode::ImportBackup,
backup.as_ref(),
Some("foobar".to_string())
)
.await
.is_err());
assert!(
imex(&context2, ImexMode::ImportBackup, backup.as_ref(), None)
.await

View File

@@ -146,6 +146,21 @@ impl Sql {
.with_context(|| format!("path {:?} is not valid unicode", path))?;
let conn = self.get_conn().await?;
// Check that backup passphrase is correct before resetting our database.
conn.execute(
"ATTACH DATABASE ? AS backup KEY ?",
paramsv![path_str, passphrase],
)
.context("failed to attach backup database")?;
if let Err(err) = conn
.query_row("SELECT count(*) FROM sqlite_master", [], |_row| Ok(()))
.context("backup passphrase is not correct")
{
conn.execute("DETACH DATABASE backup", [])
.context("failed to detach backup database")?;
return Err(err);
}
// Reset the database without reopening it. We don't want to reopen the database because we
// don't have main database passphrase at this point.
// See <https://sqlite.org/c3ref/c_dbconfig_enable_fkey.html> for documentation.
@@ -156,12 +171,6 @@ impl Sql {
.context("failed to vacuum the database")?;
conn.set_db_config(DbConfig::SQLITE_DBCONFIG_RESET_DATABASE, false)
.context("failed to unset SQLITE_DBCONFIG_RESET_DATABASE")?;
conn.execute(
"ATTACH DATABASE ? AS backup KEY ?",
paramsv![path_str, passphrase],
)
.context("failed to attach backup database")?;
let res = conn
.query_row("SELECT sqlcipher_export('main', 'backup')", [], |_row| {
Ok(())