replace chat.is_verified() by chat.is_protected()

This commit is contained in:
B. Petersen
2020-10-01 19:29:27 +02:00
parent ab8bf3c2f3
commit b8a55f3aa4
8 changed files with 46 additions and 34 deletions

View File

@@ -1329,7 +1329,7 @@ int dc_is_contact_in_chat (dc_context_t* context, uint32_t ch
* If the group is already _promoted_ (any message was sent to the group),
* all group members are informed by a special status message that is sent automatically by this function.
*
* If the group is a verified group, only verified contacts can be added to the group.
* If the group has group protection enabled, only verified contacts can be added to the group.
*
* Sends out #DC_EVENT_CHAT_MODIFIED and #DC_EVENT_MSGS_CHANGED if a status message was sent.
*
@@ -1973,7 +1973,7 @@ dc_lot_t* dc_check_qr (dc_context_t* context, const char*
* @param context The context object.
* @param chat_id If set to a group-chat-id,
* the Verified-Group-Invite protocol is offered in the QR code;
* works for verified groups as well as for normal groups.
* works for protected groups as well as for normal groups.
* If set to 0, the Setup-Contact protocol is offered in the QR code.
* See https://countermitm.readthedocs.io/en/latest/new.html
* for details about both protocols.
@@ -2003,7 +2003,7 @@ char* dc_get_securejoin_qr (dc_context_t* context, uint32_t ch
* When the protocol has finished, an info-message is added to that chat.
* - If the given QR code starts the Verified-Group-Invite protocol,
* the function waits until the protocol has finished.
* This is because the verified group is not opportunistic
* This is because the protected group is not opportunistic
* and can be created only when the contacts have verified each other.
*
* See https://countermitm.readthedocs.io/en/latest/new.html
@@ -2015,8 +2015,8 @@ char* dc_get_securejoin_qr (dc_context_t* context, uint32_t ch
* to dc_check_qr().
* @return Chat-id of the joined chat, the UI may redirect to the this chat.
* If the out-of-band verification failed or was aborted, 0 is returned.
* A returned chat-id does not guarantee that the chat or the belonging contact is verified.
* If needed, this be checked with dc_chat_is_verified() and dc_contact_is_verified(),
* A returned chat-id does not guarantee that the chat is protected or the belonging contact is verified.
* If needed, this be checked with dc_chat_is_protected() and dc_contact_is_verified(),
* however, in practise, the UI will just listen to #DC_EVENT_CONTACTS_CHANGED unconditionally.
*/
uint32_t dc_join_securejoin (dc_context_t* context, const char* qr);
@@ -2942,15 +2942,17 @@ int dc_chat_can_send (const dc_chat_t* chat);
/**
* Check if a chat is verified. Verified chats contain only verified members
* and encryption is alwasy enabled. Verified chats are created using
* dc_create_group_chat() by setting the 'verified' parameter to true.
* Check if a chat is protected.
* Protected chats contain only verified members and encryption is always enabled.
* Protected chats are created using dc_create_group_chat() by setting the 'protect' parameter to 1.
* The status can be changed using dc_set_chat_protection().
*
* @memberof dc_chat_t
* @param chat The chat object.
* @return 1=chat verified, 0=chat is not verified
* @return 1=chat protected, 0=chat is not protected
*/
int dc_chat_is_verified (const dc_chat_t* chat);
int dc_chat_is_protected (const dc_chat_t* chat);
#define dc_chat_is_verified dc_chat_is_protected // allow using old function name for a while
/**

View File

@@ -2389,13 +2389,13 @@ pub unsafe extern "C" fn dc_chat_can_send(chat: *mut dc_chat_t) -> libc::c_int {
}
#[no_mangle]
pub unsafe extern "C" fn dc_chat_is_verified(chat: *mut dc_chat_t) -> libc::c_int {
pub unsafe extern "C" fn dc_chat_is_protected(chat: *mut dc_chat_t) -> libc::c_int {
if chat.is_null() {
eprintln!("ignoring careless call to dc_chat_is_verified()");
eprintln!("ignoring careless call to dc_chat_is_protected()");
return 0;
}
let ffi_chat = &*chat;
ffi_chat.chat.is_verified() as libc::c_int
ffi_chat.chat.is_protected() as libc::c_int
}
#[no_mangle]

View File

@@ -523,7 +523,7 @@ pub async fn cmdline(context: Context, line: &str, chat_id: &mut ChatId) -> Resu
for i in (0..cnt).rev() {
let chat = Chat::load_from_db(&context, chatlist.get_chat_id(i)).await?;
println!(
"{}#{}: {} [{} fresh] {}",
"{}#{}: {} [{} fresh] {}{}",
chat_prefix(&chat),
chat.get_id(),
chat.get_name(),
@@ -533,6 +533,7 @@ pub async fn cmdline(context: Context, line: &str, chat_id: &mut ChatId) -> Resu
ChatVisibility::Archived => "📦",
ChatVisibility::Pinned => "📌",
},
if chat.is_protected() { "🛡️" } else { "" },
);
let lot = chatlist.get_summary(&context, i, Some(&chat)).await;
let statestr = if chat.visibility == ChatVisibility::Archived {
@@ -607,7 +608,7 @@ pub async fn cmdline(context: Context, line: &str, chat_id: &mut ChatId) -> Resu
format!("{} member(s)", members.len())
};
println!(
"{}#{}: {} [{}]{}{}",
"{}#{}: {} [{}]{}{} {}",
chat_prefix(sel_chat),
sel_chat.get_id(),
sel_chat.get_name(),
@@ -624,6 +625,11 @@ pub async fn cmdline(context: Context, line: &str, chat_id: &mut ChatId) -> Resu
},
_ => "".to_string(),
},
if sel_chat.is_protected() {
"🛡️"
} else {
""
},
);
log_msglist(&context, &msglist).await?;
if let Some(draft) = sel_chat.get_id().get_draft(&context).await? {

View File

@@ -85,12 +85,12 @@ class Chat(object):
"""
return not lib.dc_chat_is_unpromoted(self._dc_chat)
def is_verified(self):
def is_protected(self):
""" return True if this chat is a verified group.
:returns: True if chat is verified, False otherwise.
"""
return lib.dc_chat_is_verified(self._dc_chat)
return lib.dc_chat_is_protected(self._dc_chat)
def get_name(self):
""" return name of this chat.

View File

@@ -1343,7 +1343,7 @@ class TestOnlineAccount:
ac1, ac2 = acfactory.get_two_online_accounts()
lp.sec("ac1: create verified-group QR, ac2 scans and joins")
chat1 = ac1.create_group_chat("hello", verified=True)
assert chat1.is_verified()
assert chat1.is_protected()
qr = chat1.get_join_qr()
lp.sec("ac2: start QR-code based join-group protocol")
chat2 = ac2.qr_join_chat(qr)
@@ -1362,7 +1362,7 @@ class TestOnlineAccount:
lp.sec("ac2: read message and check it's verified chat")
msg = ac2._evtracker.wait_next_incoming_message()
assert msg.text == "hello"
assert msg.chat.is_verified()
assert msg.chat.is_protected()
assert msg.is_encrypted()
lp.sec("ac2: send message and let ac1 read it")

View File

@@ -566,6 +566,7 @@ pub struct Chat {
pub param: Params,
is_sending_locations: bool,
pub mute_duration: MuteDuration,
protected: ProtectionStatus,
}
impl Chat {
@@ -575,7 +576,7 @@ impl Chat {
.sql
.query_row(
"SELECT c.type, c.name, c.grpid, c.param, c.archived,
c.blocked, c.locations_send_until, c.muted_until
c.blocked, c.locations_send_until, c.muted_until, c.protected
FROM chats c
WHERE c.id=?;",
paramsv![chat_id],
@@ -590,6 +591,7 @@ impl Chat {
blocked: row.get::<_, Option<_>>(5)?.unwrap_or_default(),
is_sending_locations: row.get(6)?,
mute_duration: row.get(7)?,
protected: row.get(8)?,
};
Ok(c)
},
@@ -755,9 +757,9 @@ impl Chat {
!self.is_unpromoted()
}
/// Returns true if chat is a verified group chat.
pub fn is_verified(&self) -> bool {
self.typ == Chattype::VerifiedGroup
/// Returns true if chat protection is enabled.
pub fn is_protected(&self) -> bool {
self.protected == ProtectionStatus::Protected
}
/// Returns true if location streaming is enabled in the chat.
@@ -2062,7 +2064,7 @@ pub(crate) async fn add_contact_to_chat_ex(
{
error!(
context,
"Only bidirectional verified contacts can be added to verified groups."
"Only bidirectional verified contacts can be added to protected chats."
);
return Ok(false);
}
@@ -2626,7 +2628,7 @@ pub(crate) async fn get_chat_cnt(context: &Context) -> usize {
}
}
/// Returns a tuple of `(chatid, is_verified, blocked)`.
/// Returns a tuple of `(chatid, is_protected, blocked)`.
pub(crate) async fn get_chat_id_by_grpid(
context: &Context,
grpid: impl AsRef<str>,
@@ -2634,14 +2636,16 @@ pub(crate) async fn get_chat_id_by_grpid(
context
.sql
.query_row(
"SELECT id, blocked, type FROM chats WHERE grpid=?;",
"SELECT id, blocked, protected FROM chats WHERE grpid=?;",
paramsv![grpid.as_ref()],
|row| {
let chat_id = row.get::<_, ChatId>(0)?;
let b = row.get::<_, Option<Blocked>>(1)?.unwrap_or_default();
let v = row.get::<_, Option<Chattype>>(2)?.unwrap_or_default();
Ok((chat_id, v == Chattype::VerifiedGroup, b))
let p = row
.get::<_, Option<ProtectionStatus>>(2)?
.unwrap_or_default();
Ok((chat_id, p == ProtectionStatus::Protected, b))
},
)
.await

View File

@@ -1731,7 +1731,7 @@ async fn check_verified_properties(
}
if !is_verified {
bail!(
"{} is not a member of this verified group",
"{} is not a member of this protected chat",
to_addr.to_string()
);
}

View File

@@ -348,7 +348,7 @@ async fn securejoin(context: &Context, qr: &str) -> Result<ChatId, JoinError> {
let bob = context.bob.read().await;
let grpid = bob.qr_scan.as_ref().unwrap().text2.as_ref().unwrap();
match chat::get_chat_id_by_grpid(context, grpid).await {
Ok((chatid, _is_verified, _blocked)) => break chatid,
Ok((chatid, _is_protected, _blocked)) => break chatid,
Err(err) => {
if start.elapsed() > Duration::from_secs(7) {
return Err(JoinError::MissingChat(err));
@@ -791,19 +791,19 @@ pub(crate) async fn handle_securejoin_handshake(
let vg_expect_encrypted = if join_vg {
let group_id = get_qr_attr!(context, text2).to_string();
// This is buggy, is_verified_group will always be
// This is buggy, is_protected_group will always be
// false since the group is created by receive_imf by
// the very handshake message we're handling now. But
// only after we have returned. It does not impact
// the security invariants of secure-join however.
let (_, is_verified_group, _) = chat::get_chat_id_by_grpid(context, &group_id)
let (_, is_protected_group, _) = chat::get_chat_id_by_grpid(context, &group_id)
.await
.unwrap_or((ChatId::new(0), false, Blocked::Not));
// when joining a non-verified group
// the vg-member-added message may be unencrypted
// when not all group members have keys or prefer encryption.
// So only expect encryption if this is a verified group
is_verified_group
is_protected_group
} else {
// setup contact is always encrypted
true
@@ -1428,6 +1428,6 @@ mod tests {
let bob_chatid = joiner.await;
let bob_chat = Chat::load_from_db(&bob.ctx, bob_chatid).await.unwrap();
assert!(bob_chat.is_verified());
assert!(bob_chat.is_protected());
}
}