Skip to content

Commit

Permalink
feat: make sqlcipher configurable
Browse files Browse the repository at this point in the history
  • Loading branch information
dignifiedquire committed May 12, 2024
1 parent a04fe0a commit 46039cb
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 7 deletions.
5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ quoted_printable = "0.5"
rand = "0.8"
regex = { workspace = true }
reqwest = { version = "0.12.2", features = ["json"] }
rusqlite = { workspace = true, features = ["sqlcipher"] }
rusqlite = { workspace = true }
rust-hsluv = "0.1"
sanitize-filename = "0.5"
serde_json = "1"
Expand Down Expand Up @@ -172,8 +172,9 @@ rusqlite = "0.31"
chrono = { version = "0.4.38", default-features=false, features = ["alloc", "clock", "std"] }

[features]
default = ["vendored"]
default = ["vendored", "sqlcipher"]
internals = []
sqlcipher = ["rusqlite/sqlcipher"]
vendored = [
"async-native-tls/vendored",
"rusqlite/bundled-sqlcipher-vendored-openssl",
Expand Down
1 change: 1 addition & 0 deletions src/accounts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -934,6 +934,7 @@ mod tests {
}

#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
#[cfg(feature = "sqlcipher")]
async fn test_encrypted_account() -> Result<()> {
let dir = tempfile::tempdir().context("failed to create tempdir")?;
let p: PathBuf = dir.path().join("accounts");
Expand Down
33 changes: 28 additions & 5 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,9 +337,17 @@ impl Context {
Self::new_closed(dbfile, id, events, stock_strings, Default::default()).await?;

// Open the database if is not encrypted.
if context.check_passphrase("".to_string()).await? {
#[cfg(feature = "sqlcipher")]
{
if context.check_passphrase("".to_string()).await? {
context.sql.open(&context, "".to_string()).await?;
}
}
#[cfg(not(feature = "sqlcipher"))]
{
context.sql.open(&context, "".to_string()).await?;
}

Ok(context)
}

Expand Down Expand Up @@ -374,15 +382,24 @@ impl Context {
/// Returns true if passphrase is correct, false is passphrase is not correct. Fails on other
/// errors.
pub async fn open(&self, passphrase: String) -> Result<bool> {
if self.sql.check_passphrase(passphrase.clone()).await? {
#[cfg(feature = "sqlcipher")]
{
if self.sql.check_passphrase(passphrase.clone()).await? {
self.sql.open(self, passphrase).await?;
Ok(true)
} else {
Ok(false)
}
}
#[cfg(not(feature = "sqlcipher"))]
{
self.sql.open(self, passphrase).await?;
Ok(true)
} else {
Ok(false)
}
}

/// Changes encrypted database passphrase.
#[cfg(feature = "sqlcipher")]
pub async fn change_passphrase(&self, passphrase: String) -> Result<()> {
self.sql.change_passphrase(passphrase).await?;
Ok(())
Expand All @@ -398,6 +415,7 @@ impl Context {
/// Returns true if passphrase is correct.
///
/// Fails if database is already open.
#[cfg(feature = "sqlcipher")]
pub(crate) async fn check_passphrase(&self, passphrase: String) -> Result<bool> {
self.sql.check_passphrase(passphrase).await
}
Expand Down Expand Up @@ -1371,10 +1389,13 @@ pub fn get_version_str() -> &'static str {

#[cfg(test)]
mod tests {
#[cfg(feature = "sqlcipher")]
use anyhow::Context as _;
use strum::IntoEnumIterator;
#[cfg(feature = "sqlcipher")]
use tempfile::tempdir;

use strum::IntoEnumIterator;

use super::*;
use crate::chat::{get_chat_contacts, get_chat_msgs, send_msg, set_muted, Chat, MuteDuration};
use crate::chatlist::Chatlist;
Expand Down Expand Up @@ -1809,6 +1830,7 @@ mod tests {
}

#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
#[cfg(feature = "sqlcipher")]
async fn test_check_passphrase() -> Result<()> {
let dir = tempdir()?;
let dbfile = dir.path().join("db.sqlite");
Expand Down Expand Up @@ -1836,6 +1858,7 @@ mod tests {
}

#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
#[cfg(feature = "sqlcipher")]
async fn test_context_change_passphrase() -> Result<()> {
let dir = tempdir()?;
let dbfile = dir.path().join("db.sqlite");
Expand Down
2 changes: 2 additions & 0 deletions src/imex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -799,6 +799,7 @@ async fn export_database(
.ok();
conn.execute("ATTACH DATABASE ? AS backup KEY ?", (dest, passphrase))
.context("failed to attach backup database")?;
#[cfg(feature = "sqlcipher")]
let res = conn
.query_row("SELECT sqlcipher_export('backup')", [], |_row| Ok(()))
.context("failed to export to attached backup database");
Expand All @@ -809,6 +810,7 @@ async fn export_database(
.ok(); // If verified_one_on_one_chats was not set, this errors, which we ignore
conn.execute("DETACH DATABASE backup", [])
.context("failed to detach backup database")?;
#[cfg(feature = "sqlcipher")]
res?;
Ok(())
})
Expand Down
4 changes: 4 additions & 0 deletions src/sql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ impl Sql {
/// corrupted.
///
/// Fails if database is already open.
#[cfg(feature = "sqlcipher")]
pub async fn check_passphrase(&self, passphrase: String) -> Result<bool> {
if self.is_open().await {
bail!("Database is already opened.");
Expand Down Expand Up @@ -311,6 +312,7 @@ impl Sql {
/// The database must already be encrypted and the passphrase cannot be empty.
/// It is impossible to turn encrypted database into unencrypted
/// and vice versa this way, use import/export for this.
#[cfg(feature = "sqlcipher")]
pub async fn change_passphrase(&self, passphrase: String) -> Result<()> {
let mut lock = self.pool.write().await;

Expand Down Expand Up @@ -1229,6 +1231,7 @@ mod tests {
}

#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
#[cfg(feature = "sqlcipher")]
async fn test_check_passphrase() -> Result<()> {
use tempfile::tempdir;

Expand Down Expand Up @@ -1262,6 +1265,7 @@ mod tests {
}

#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
#[cfg(feature = "sqlcipher")]
async fn test_sql_change_passphrase() -> Result<()> {
use tempfile::tempdir;

Expand Down

0 comments on commit 46039cb

Please sign in to comment.