mirror of
https://github.com/chatmail/core.git
synced 2026-05-17 05:46:30 +03:00
api!: remove e2ee_enabled preference
The setting is already removed from the UIs, but users who had it disabled previously have no way to enable it. After this change encryption is effectively always preferred.
This commit is contained in:
@@ -415,7 +415,6 @@ char* dc_get_blobdir (const dc_context_t* context);
|
|||||||
* As for `displayname` and `selfstatus`, also the avatar is sent to the recipients.
|
* As for `displayname` and `selfstatus`, also the avatar is sent to the recipients.
|
||||||
* To save traffic, however, the avatar is attached only as needed
|
* To save traffic, however, the avatar is attached only as needed
|
||||||
* and also recoded to a reasonable size.
|
* and also recoded to a reasonable size.
|
||||||
* - `e2ee_enabled` = 0=no end-to-end-encryption, 1=prefer end-to-end-encryption (default)
|
|
||||||
* - `mdns_enabled` = 0=do not send or request read receipts,
|
* - `mdns_enabled` = 0=do not send or request read receipts,
|
||||||
* 1=send and request read receipts
|
* 1=send and request read receipts
|
||||||
* default=send and request read receipts, only send but not request if `bot` is set
|
* default=send and request read receipts, only send but not request if `bot` is set
|
||||||
|
|||||||
@@ -151,10 +151,6 @@ pub enum Config {
|
|||||||
/// setting up a second device, or receiving a sync message.
|
/// setting up a second device, or receiving a sync message.
|
||||||
BccSelf,
|
BccSelf,
|
||||||
|
|
||||||
/// True if encryption is preferred according to Autocrypt standard.
|
|
||||||
#[strum(props(default = "1"))]
|
|
||||||
E2eeEnabled,
|
|
||||||
|
|
||||||
/// True if Message Delivery Notifications (read receipts) should
|
/// True if Message Delivery Notifications (read receipts) should
|
||||||
/// be sent and requested.
|
/// be sent and requested.
|
||||||
#[strum(props(default = "1"))]
|
#[strum(props(default = "1"))]
|
||||||
@@ -705,7 +701,6 @@ impl Context {
|
|||||||
Config::Socks5Enabled
|
Config::Socks5Enabled
|
||||||
| Config::ProxyEnabled
|
| Config::ProxyEnabled
|
||||||
| Config::BccSelf
|
| Config::BccSelf
|
||||||
| Config::E2eeEnabled
|
|
||||||
| Config::MdnsEnabled
|
| Config::MdnsEnabled
|
||||||
| Config::SentboxWatch
|
| Config::SentboxWatch
|
||||||
| Config::MvboxMove
|
| Config::MvboxMove
|
||||||
|
|||||||
@@ -833,7 +833,6 @@ impl Context {
|
|||||||
.query_get_value("PRAGMA journal_mode;", ())
|
.query_get_value("PRAGMA journal_mode;", ())
|
||||||
.await?
|
.await?
|
||||||
.unwrap_or_else(|| "unknown".to_string());
|
.unwrap_or_else(|| "unknown".to_string());
|
||||||
let e2ee_enabled = self.get_config_int(Config::E2eeEnabled).await?;
|
|
||||||
let mdns_enabled = self.get_config_int(Config::MdnsEnabled).await?;
|
let mdns_enabled = self.get_config_int(Config::MdnsEnabled).await?;
|
||||||
let bcc_self = self.get_config_int(Config::BccSelf).await?;
|
let bcc_self = self.get_config_int(Config::BccSelf).await?;
|
||||||
let sync_msgs = self.get_config_int(Config::SyncMsgs).await?;
|
let sync_msgs = self.get_config_int(Config::SyncMsgs).await?;
|
||||||
@@ -967,7 +966,6 @@ impl Context {
|
|||||||
res.insert("configured_mvbox_folder", configured_mvbox_folder);
|
res.insert("configured_mvbox_folder", configured_mvbox_folder);
|
||||||
res.insert("configured_trash_folder", configured_trash_folder);
|
res.insert("configured_trash_folder", configured_trash_folder);
|
||||||
res.insert("mdns_enabled", mdns_enabled.to_string());
|
res.insert("mdns_enabled", mdns_enabled.to_string());
|
||||||
res.insert("e2ee_enabled", e2ee_enabled.to_string());
|
|
||||||
res.insert("bcc_self", bcc_self.to_string());
|
res.insert("bcc_self", bcc_self.to_string());
|
||||||
res.insert("sync_msgs", sync_msgs.to_string());
|
res.insert("sync_msgs", sync_msgs.to_string());
|
||||||
res.insert("disable_idle", disable_idle.to_string());
|
res.insert("disable_idle", disable_idle.to_string());
|
||||||
|
|||||||
@@ -4,10 +4,8 @@ use std::io::Cursor;
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use mail_builder::mime::MimePart;
|
use mail_builder::mime::MimePart;
|
||||||
use num_traits::FromPrimitive;
|
|
||||||
|
|
||||||
use crate::aheader::{Aheader, EncryptPreference};
|
use crate::aheader::{Aheader, EncryptPreference};
|
||||||
use crate::config::Config;
|
|
||||||
use crate::context::Context;
|
use crate::context::Context;
|
||||||
use crate::key::{SignedPublicKey, load_self_public_key, load_self_secret_key};
|
use crate::key::{SignedPublicKey, load_self_public_key, load_self_secret_key};
|
||||||
use crate::pgp;
|
use crate::pgp;
|
||||||
@@ -21,9 +19,7 @@ pub struct EncryptHelper {
|
|||||||
|
|
||||||
impl EncryptHelper {
|
impl EncryptHelper {
|
||||||
pub async fn new(context: &Context) -> Result<EncryptHelper> {
|
pub async fn new(context: &Context) -> Result<EncryptHelper> {
|
||||||
let prefer_encrypt =
|
let prefer_encrypt = EncryptPreference::Mutual;
|
||||||
EncryptPreference::from_i32(context.get_config_int(Config::E2eeEnabled).await?)
|
|
||||||
.unwrap_or_default();
|
|
||||||
let addr = context.get_primary_self_addr().await?;
|
let addr = context.get_primary_self_addr().await?;
|
||||||
let public_key = load_self_public_key(context).await?;
|
let public_key = load_self_public_key(context).await?;
|
||||||
|
|
||||||
|
|||||||
26
src/imex.rs
26
src/imex.rs
@@ -140,32 +140,8 @@ pub async fn has_backup(_context: &Context, dir_name: &Path) -> Result<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn set_self_key(context: &Context, armored: &str) -> Result<()> {
|
async fn set_self_key(context: &Context, armored: &str) -> Result<()> {
|
||||||
// try hard to only modify key-state
|
let private_key = SignedSecretKey::from_asc(armored)?;
|
||||||
let (private_key, header) = SignedSecretKey::from_asc(armored)?;
|
|
||||||
let public_key = private_key.split_public_key()?;
|
let public_key = private_key.split_public_key()?;
|
||||||
if let Some(preferencrypt) = header.get("Autocrypt-Prefer-Encrypt") {
|
|
||||||
let e2ee_enabled = match preferencrypt.as_str() {
|
|
||||||
"nopreference" => 0,
|
|
||||||
"mutual" => 1,
|
|
||||||
_ => {
|
|
||||||
bail!("invalid Autocrypt-Prefer-Encrypt header: {:?}", header);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
context
|
|
||||||
.sql
|
|
||||||
.set_raw_config_int("e2ee_enabled", e2ee_enabled)
|
|
||||||
.await?;
|
|
||||||
} else {
|
|
||||||
// `Autocrypt-Prefer-Encrypt` is not included
|
|
||||||
// in keys exported to file.
|
|
||||||
//
|
|
||||||
// `Autocrypt-Prefer-Encrypt` also SHOULD be sent
|
|
||||||
// in Autocrypt Setup Message according to Autocrypt specification,
|
|
||||||
// but K-9 6.802 does not include this header.
|
|
||||||
//
|
|
||||||
// We keep current setting in this case.
|
|
||||||
info!(context, "No Autocrypt-Prefer-Encrypt header.");
|
|
||||||
};
|
|
||||||
|
|
||||||
let keypair = pgp::KeyPair {
|
let keypair = pgp::KeyPair {
|
||||||
public: public_key,
|
public: public_key,
|
||||||
|
|||||||
@@ -93,10 +93,7 @@ pub async fn render_setup_file(context: &Context, passphrase: &str) -> Result<St
|
|||||||
bail!("Passphrase must be at least 2 chars long.");
|
bail!("Passphrase must be at least 2 chars long.");
|
||||||
};
|
};
|
||||||
let private_key = load_self_secret_key(context).await?;
|
let private_key = load_self_secret_key(context).await?;
|
||||||
let ac_headers = match context.get_config_bool(Config::E2eeEnabled).await? {
|
let ac_headers = Some(("Autocrypt-Prefer-Encrypt", "mutual"));
|
||||||
false => None,
|
|
||||||
true => Some(("Autocrypt-Prefer-Encrypt", "mutual")),
|
|
||||||
};
|
|
||||||
let private_key_asc = private_key.to_asc(ac_headers);
|
let private_key_asc = private_key.to_asc(ac_headers);
|
||||||
let encr = pgp::symm_encrypt(passphrase, private_key_asc.into_bytes())
|
let encr = pgp::symm_encrypt(passphrase, private_key_asc.into_bytes())
|
||||||
.await?
|
.await?
|
||||||
|
|||||||
32
src/key.rs
32
src/key.rs
@@ -71,31 +71,17 @@ pub(crate) trait DcKey: Serialize + Deserializable + Clone {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create a key from an ASCII-armored string.
|
/// Create a key from an ASCII-armored string.
|
||||||
///
|
fn from_asc(data: &str) -> Result<Self> {
|
||||||
/// Returns the key and a map of any headers which might have been set in
|
|
||||||
/// the ASCII-armored representation.
|
|
||||||
fn from_asc(data: &str) -> Result<(Self, BTreeMap<String, String>)> {
|
|
||||||
let bytes = data.as_bytes();
|
let bytes = data.as_bytes();
|
||||||
let res = Self::from_armor_single(Cursor::new(bytes));
|
let res = Self::from_armor_single(Cursor::new(bytes));
|
||||||
let (key, headers) = match res {
|
let (key, _headers) = match res {
|
||||||
Err(pgp::errors::Error::NoMatchingPacket { .. }) => match Self::is_private() {
|
Err(pgp::errors::Error::NoMatchingPacket { .. }) => match Self::is_private() {
|
||||||
true => bail!("No private key packet found"),
|
true => bail!("No private key packet found"),
|
||||||
false => bail!("No public key packet found"),
|
false => bail!("No public key packet found"),
|
||||||
},
|
},
|
||||||
_ => res.context("rPGP error")?,
|
_ => res.context("rPGP error")?,
|
||||||
};
|
};
|
||||||
let headers = headers
|
Ok(key)
|
||||||
.into_iter()
|
|
||||||
.map(|(key, values)| {
|
|
||||||
(
|
|
||||||
key.trim().to_lowercase(),
|
|
||||||
values
|
|
||||||
.last()
|
|
||||||
.map_or_else(String::new, |s| s.trim().to_string()),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
Ok((key, headers))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Serialise the key as bytes.
|
/// Serialise the key as bytes.
|
||||||
@@ -446,7 +432,7 @@ pub(crate) async fn store_self_keypair(context: &Context, keypair: &KeyPair) ->
|
|||||||
/// to avoid generating the key in tests.
|
/// to avoid generating the key in tests.
|
||||||
/// Use import/export APIs instead.
|
/// Use import/export APIs instead.
|
||||||
pub async fn preconfigure_keypair(context: &Context, secret_data: &str) -> Result<()> {
|
pub async fn preconfigure_keypair(context: &Context, secret_data: &str) -> Result<()> {
|
||||||
let secret = SignedSecretKey::from_asc(secret_data)?.0;
|
let secret = SignedSecretKey::from_asc(secret_data)?;
|
||||||
let public = secret.split_public_key()?;
|
let public = secret.split_public_key()?;
|
||||||
let keypair = KeyPair { public, secret };
|
let keypair = KeyPair { public, secret };
|
||||||
store_self_keypair(context, &keypair).await?;
|
store_self_keypair(context, &keypair).await?;
|
||||||
@@ -532,7 +518,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_from_armored_string() {
|
fn test_from_armored_string() {
|
||||||
let (private_key, _) = SignedSecretKey::from_asc(
|
let private_key = SignedSecretKey::from_asc(
|
||||||
"-----BEGIN PGP PRIVATE KEY BLOCK-----
|
"-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||||
|
|
||||||
xcLYBF0fgz4BCADnRUV52V4xhSsU56ZaAn3+3oG86MZhXy4X8w14WZZDf0VJGeTh
|
xcLYBF0fgz4BCADnRUV52V4xhSsU56ZaAn3+3oG86MZhXy4X8w14WZZDf0VJGeTh
|
||||||
@@ -600,17 +586,13 @@ i8pcjGO+IZffvyZJVRWfVooBJmWWbPB1pueo3tx8w3+fcuzpxz+RLFKaPyqXO+dD
|
|||||||
fn test_asc_roundtrip() {
|
fn test_asc_roundtrip() {
|
||||||
let key = KEYPAIR.public.clone();
|
let key = KEYPAIR.public.clone();
|
||||||
let asc = key.to_asc(Some(("spam", "ham")));
|
let asc = key.to_asc(Some(("spam", "ham")));
|
||||||
let (key2, hdrs) = SignedPublicKey::from_asc(&asc).unwrap();
|
let key2 = SignedPublicKey::from_asc(&asc).unwrap();
|
||||||
assert_eq!(key, key2);
|
assert_eq!(key, key2);
|
||||||
assert_eq!(hdrs.len(), 1);
|
|
||||||
assert_eq!(hdrs.get("spam"), Some(&String::from("ham")));
|
|
||||||
|
|
||||||
let key = KEYPAIR.secret.clone();
|
let key = KEYPAIR.secret.clone();
|
||||||
let asc = key.to_asc(Some(("spam", "ham")));
|
let asc = key.to_asc(Some(("spam", "ham")));
|
||||||
let (key2, hdrs) = SignedSecretKey::from_asc(&asc).unwrap();
|
let key2 = SignedSecretKey::from_asc(&asc).unwrap();
|
||||||
assert_eq!(key, key2);
|
assert_eq!(key, key2);
|
||||||
assert_eq!(hdrs.len(), 1);
|
|
||||||
assert_eq!(hdrs.get("spam"), Some(&String::from("ham")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -1519,7 +1519,7 @@ impl MimeMessage {
|
|||||||
);
|
);
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
Ok((key, _)) => key,
|
Ok(key) => key,
|
||||||
};
|
};
|
||||||
if let Err(err) = key.verify() {
|
if let Err(err) = key.verify() {
|
||||||
warn!(context, "Attached PGP key verification failed: {err:#}.");
|
warn!(context, "Attached PGP key verification failed: {err:#}.");
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ fn pad_device_token(s: &str) -> String {
|
|||||||
///
|
///
|
||||||
/// The result is base64-encoded and not ASCII armored to avoid dealing with newlines.
|
/// The result is base64-encoded and not ASCII armored to avoid dealing with newlines.
|
||||||
pub(crate) fn encrypt_device_token(device_token: &str) -> Result<String> {
|
pub(crate) fn encrypt_device_token(device_token: &str) -> Result<String> {
|
||||||
let public_key = pgp::composed::SignedPublicKey::from_asc(NOTIFIERS_PUBLIC_KEY)?.0;
|
let public_key = pgp::composed::SignedPublicKey::from_asc(NOTIFIERS_PUBLIC_KEY)?;
|
||||||
let encryption_subkey = public_key
|
let encryption_subkey = public_key
|
||||||
.public_subkeys
|
.public_subkeys
|
||||||
.first()
|
.first()
|
||||||
|
|||||||
@@ -1245,9 +1245,8 @@ impl SentMessage<'_> {
|
|||||||
///
|
///
|
||||||
/// The keypair was created using the crate::key::tests::gen_key test.
|
/// The keypair was created using the crate::key::tests::gen_key test.
|
||||||
pub fn alice_keypair() -> KeyPair {
|
pub fn alice_keypair() -> KeyPair {
|
||||||
let secret = key::SignedSecretKey::from_asc(include_str!("../test-data/key/alice-secret.asc"))
|
let secret =
|
||||||
.unwrap()
|
key::SignedSecretKey::from_asc(include_str!("../test-data/key/alice-secret.asc")).unwrap();
|
||||||
.0;
|
|
||||||
let public = secret.split_public_key().unwrap();
|
let public = secret.split_public_key().unwrap();
|
||||||
KeyPair { public, secret }
|
KeyPair { public, secret }
|
||||||
}
|
}
|
||||||
@@ -1256,9 +1255,8 @@ pub fn alice_keypair() -> KeyPair {
|
|||||||
///
|
///
|
||||||
/// Like [alice_keypair] but a different key and identity.
|
/// Like [alice_keypair] but a different key and identity.
|
||||||
pub fn bob_keypair() -> KeyPair {
|
pub fn bob_keypair() -> KeyPair {
|
||||||
let secret = key::SignedSecretKey::from_asc(include_str!("../test-data/key/bob-secret.asc"))
|
let secret =
|
||||||
.unwrap()
|
key::SignedSecretKey::from_asc(include_str!("../test-data/key/bob-secret.asc")).unwrap();
|
||||||
.0;
|
|
||||||
let public = secret.split_public_key().unwrap();
|
let public = secret.split_public_key().unwrap();
|
||||||
KeyPair { public, secret }
|
KeyPair { public, secret }
|
||||||
}
|
}
|
||||||
@@ -1269,8 +1267,7 @@ pub fn bob_keypair() -> KeyPair {
|
|||||||
pub fn charlie_keypair() -> KeyPair {
|
pub fn charlie_keypair() -> KeyPair {
|
||||||
let secret =
|
let secret =
|
||||||
key::SignedSecretKey::from_asc(include_str!("../test-data/key/charlie-secret.asc"))
|
key::SignedSecretKey::from_asc(include_str!("../test-data/key/charlie-secret.asc"))
|
||||||
.unwrap()
|
.unwrap();
|
||||||
.0;
|
|
||||||
let public = secret.split_public_key().unwrap();
|
let public = secret.split_public_key().unwrap();
|
||||||
KeyPair { public, secret }
|
KeyPair { public, secret }
|
||||||
}
|
}
|
||||||
@@ -1279,9 +1276,8 @@ pub fn charlie_keypair() -> KeyPair {
|
|||||||
///
|
///
|
||||||
/// Like [alice_keypair] but a different key and identity.
|
/// Like [alice_keypair] but a different key and identity.
|
||||||
pub fn dom_keypair() -> KeyPair {
|
pub fn dom_keypair() -> KeyPair {
|
||||||
let secret = key::SignedSecretKey::from_asc(include_str!("../test-data/key/dom-secret.asc"))
|
let secret =
|
||||||
.unwrap()
|
key::SignedSecretKey::from_asc(include_str!("../test-data/key/dom-secret.asc")).unwrap();
|
||||||
.0;
|
|
||||||
let public = secret.split_public_key().unwrap();
|
let public = secret.split_public_key().unwrap();
|
||||||
KeyPair { public, secret }
|
KeyPair { public, secret }
|
||||||
}
|
}
|
||||||
@@ -1290,9 +1286,8 @@ pub fn dom_keypair() -> KeyPair {
|
|||||||
///
|
///
|
||||||
/// Like [alice_keypair] but a different key and identity.
|
/// Like [alice_keypair] but a different key and identity.
|
||||||
pub fn elena_keypair() -> KeyPair {
|
pub fn elena_keypair() -> KeyPair {
|
||||||
let secret = key::SignedSecretKey::from_asc(include_str!("../test-data/key/elena-secret.asc"))
|
let secret =
|
||||||
.unwrap()
|
key::SignedSecretKey::from_asc(include_str!("../test-data/key/elena-secret.asc")).unwrap();
|
||||||
.0;
|
|
||||||
let public = secret.split_public_key().unwrap();
|
let public = secret.split_public_key().unwrap();
|
||||||
KeyPair { public, secret }
|
KeyPair { public, secret }
|
||||||
}
|
}
|
||||||
@@ -1301,9 +1296,8 @@ pub fn elena_keypair() -> KeyPair {
|
|||||||
///
|
///
|
||||||
/// Like [alice_keypair] but a different key and identity.
|
/// Like [alice_keypair] but a different key and identity.
|
||||||
pub fn fiona_keypair() -> KeyPair {
|
pub fn fiona_keypair() -> KeyPair {
|
||||||
let secret = key::SignedSecretKey::from_asc(include_str!("../test-data/key/fiona-secret.asc"))
|
let secret =
|
||||||
.unwrap()
|
key::SignedSecretKey::from_asc(include_str!("../test-data/key/fiona-secret.asc")).unwrap();
|
||||||
.0;
|
|
||||||
let public = secret.split_public_key().unwrap();
|
let public = secret.split_public_key().unwrap();
|
||||||
KeyPair { public, secret }
|
KeyPair { public, secret }
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user