mirror of
https://github.com/chatmail/core.git
synced 2026-05-08 09:26:29 +03:00
start save implementation of save keys
This commit is contained in:
@@ -512,7 +512,7 @@ pub const DC_STR_COUNT: usize = 66;
|
|||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive, ToPrimitive)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum Key {
|
pub enum KeyType {
|
||||||
Public = 0,
|
Public = 0,
|
||||||
Private = 1,
|
Private = 1,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,12 +50,12 @@ impl str::FromStr for EncryptPreference {
|
|||||||
/// Parse and create [Autocrypt-headers](https://autocrypt.org/en/latest/level1.html#the-autocrypt-header).
|
/// Parse and create [Autocrypt-headers](https://autocrypt.org/en/latest/level1.html#the-autocrypt-header).
|
||||||
pub struct Aheader {
|
pub struct Aheader {
|
||||||
pub addr: String,
|
pub addr: String,
|
||||||
pub public_key: *mut dc_key_t,
|
pub public_key: Key,
|
||||||
pub prefer_encrypt: EncryptPreference,
|
pub prefer_encrypt: EncryptPreference,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Aheader {
|
impl Aheader {
|
||||||
pub fn new(addr: String, public_key: *mut dc_key_t, prefer_encrypt: EncryptPreference) -> Self {
|
pub fn new(addr: String, public_key: Key, prefer_encrypt: EncryptPreference) -> Self {
|
||||||
Aheader {
|
Aheader {
|
||||||
addr,
|
addr,
|
||||||
public_key,
|
public_key,
|
||||||
@@ -122,7 +122,7 @@ impl fmt::Display for Aheader {
|
|||||||
// adds a whitespace every 78 characters, this allows libEtPan to
|
// adds a whitespace every 78 characters, this allows libEtPan to
|
||||||
// wrap the lines according to RFC 5322
|
// wrap the lines according to RFC 5322
|
||||||
// (which may insert a linebreak before every whitespace)
|
// (which may insert a linebreak before every whitespace)
|
||||||
let keydata = dc_key_render_base64_string(self.public_key, 78);
|
let keydata = self.public_key.to_base64(78);
|
||||||
write!(
|
write!(
|
||||||
fmt,
|
fmt,
|
||||||
"addr={}; prefer-encrypt={}; keydata={}",
|
"addr={}; prefer-encrypt={}; keydata={}",
|
||||||
@@ -158,17 +158,7 @@ impl str::FromStr for Aheader {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let public_key = match attributes.remove("keydata") {
|
let public_key = match attributes.remove("keydata") {
|
||||||
Some(raw) => {
|
Some(raw) => Key::from_base64(raw, KeyType::Public),
|
||||||
let key = unsafe { dc_key_new() };
|
|
||||||
unsafe {
|
|
||||||
dc_key_set_from_base64(
|
|
||||||
key,
|
|
||||||
CString::new(raw).unwrap().as_ptr(),
|
|
||||||
Key::Public.to_i32().unwrap(),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
key
|
|
||||||
}
|
|
||||||
None => {
|
None => {
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
@@ -196,15 +186,6 @@ impl str::FromStr for Aheader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Aheader {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
unsafe {
|
|
||||||
dc_key_unref(self.public_key);
|
|
||||||
}
|
|
||||||
self.public_key = std::ptr::null_mut();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ use crate::x::*;
|
|||||||
* @class dc_apeerstate_t
|
* @class dc_apeerstate_t
|
||||||
* Library-internal.
|
* Library-internal.
|
||||||
*/
|
*/
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct dc_apeerstate_t<'a> {
|
pub struct dc_apeerstate_t<'a> {
|
||||||
pub context: &'a dc_context_t,
|
pub context: &'a dc_context_t,
|
||||||
@@ -25,130 +24,128 @@ pub struct dc_apeerstate_t<'a> {
|
|||||||
pub last_seen: time_t,
|
pub last_seen: time_t,
|
||||||
pub last_seen_autocrypt: time_t,
|
pub last_seen_autocrypt: time_t,
|
||||||
pub prefer_encrypt: libc::c_int,
|
pub prefer_encrypt: libc::c_int,
|
||||||
pub public_key: *mut dc_key_t,
|
pub public_key: Option<Key>,
|
||||||
pub public_key_fingerprint: *mut libc::c_char,
|
pub public_key_fingerprint: *mut libc::c_char,
|
||||||
pub gossip_key: *mut dc_key_t,
|
pub gossip_key: Option<Key>,
|
||||||
pub gossip_timestamp: time_t,
|
pub gossip_timestamp: time_t,
|
||||||
pub gossip_key_fingerprint: *mut libc::c_char,
|
pub gossip_key_fingerprint: *mut libc::c_char,
|
||||||
pub verified_key: *mut dc_key_t,
|
// TODO: this should be a reference to either the public_key or verified_key
|
||||||
|
pub verified_key: Option<Key>,
|
||||||
pub verified_key_fingerprint: *mut libc::c_char,
|
pub verified_key_fingerprint: *mut libc::c_char,
|
||||||
pub to_save: libc::c_int,
|
pub to_save: libc::c_int,
|
||||||
pub degrade_event: libc::c_int,
|
pub degrade_event: libc::c_int,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the returned pointer is ref'd and must be unref'd after usage */
|
/* the returned pointer is ref'd and must be unref'd after usage */
|
||||||
pub unsafe fn dc_apeerstate_new<'a>(context: &'a dc_context_t) -> *mut dc_apeerstate_t<'a> {
|
pub fn dc_apeerstate_new<'a>(context: &'a dc_context_t) -> dc_apeerstate_t<'a> {
|
||||||
let mut peerstate: *mut dc_apeerstate_t;
|
dc_apeerstate_t {
|
||||||
peerstate = calloc(1, ::std::mem::size_of::<dc_apeerstate_t>()) as *mut dc_apeerstate_t;
|
context,
|
||||||
if peerstate.is_null() {
|
addr: std::ptr::null_mut(),
|
||||||
exit(43i32);
|
last_seen: 0,
|
||||||
|
last_seen_autocrypt: 0,
|
||||||
|
prefer_encrypt: 0,
|
||||||
|
public_key: None,
|
||||||
|
public_key_fingerprint: std::ptr::null_mut(),
|
||||||
|
gossip_key: None,
|
||||||
|
gossip_key_fingerprint: std::ptr::null_mut(),
|
||||||
|
gossip_timestamp: 0,
|
||||||
|
verified_key: None,
|
||||||
|
verified_key_fingerprint: std::ptr::null_mut(),
|
||||||
|
to_save: 0,
|
||||||
|
degrade_event: 0,
|
||||||
}
|
}
|
||||||
(*peerstate).context = context;
|
|
||||||
|
|
||||||
peerstate
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn dc_apeerstate_unref(peerstate: *mut dc_apeerstate_t) {
|
pub unsafe fn dc_apeerstate_unref(peerstate: &mut dc_apeerstate_t) {
|
||||||
dc_apeerstate_empty(peerstate);
|
dc_apeerstate_empty(peerstate);
|
||||||
free(peerstate as *mut libc::c_void);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* dc_apeerstate_t represents the state of an Autocrypt peer - Load/save
|
* dc_apeerstate_t represents the state of an Autocrypt peer - Load/save
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
unsafe fn dc_apeerstate_empty(mut peerstate: *mut dc_apeerstate_t) {
|
unsafe fn dc_apeerstate_empty(peerstate: &mut dc_apeerstate_t) {
|
||||||
if peerstate.is_null() {
|
peerstate.last_seen = 0i32 as time_t;
|
||||||
return;
|
peerstate.last_seen_autocrypt = 0i32 as time_t;
|
||||||
}
|
peerstate.prefer_encrypt = 0i32;
|
||||||
(*peerstate).last_seen = 0i32 as time_t;
|
peerstate.to_save = 0i32;
|
||||||
(*peerstate).last_seen_autocrypt = 0i32 as time_t;
|
free(peerstate.addr as *mut libc::c_void);
|
||||||
(*peerstate).prefer_encrypt = 0i32;
|
peerstate.addr = 0 as *mut libc::c_char;
|
||||||
(*peerstate).to_save = 0i32;
|
free(peerstate.public_key_fingerprint as *mut libc::c_void);
|
||||||
free((*peerstate).addr as *mut libc::c_void);
|
peerstate.public_key_fingerprint = 0 as *mut libc::c_char;
|
||||||
(*peerstate).addr = 0 as *mut libc::c_char;
|
free(peerstate.gossip_key_fingerprint as *mut libc::c_void);
|
||||||
free((*peerstate).public_key_fingerprint as *mut libc::c_void);
|
peerstate.gossip_key_fingerprint = 0 as *mut libc::c_char;
|
||||||
(*peerstate).public_key_fingerprint = 0 as *mut libc::c_char;
|
free(peerstate.verified_key_fingerprint as *mut libc::c_void);
|
||||||
free((*peerstate).gossip_key_fingerprint as *mut libc::c_void);
|
peerstate.verified_key_fingerprint = 0 as *mut libc::c_char;
|
||||||
(*peerstate).gossip_key_fingerprint = 0 as *mut libc::c_char;
|
|
||||||
free((*peerstate).verified_key_fingerprint as *mut libc::c_void);
|
peerstate.public_key = None;
|
||||||
(*peerstate).verified_key_fingerprint = 0 as *mut libc::c_char;
|
peerstate.gossip_timestamp = 0i32 as time_t;
|
||||||
dc_key_unref((*peerstate).public_key);
|
peerstate.gossip_key = None;
|
||||||
(*peerstate).public_key = 0 as *mut dc_key_t;
|
peerstate.verified_key = None;
|
||||||
(*peerstate).gossip_timestamp = 0i32 as time_t;
|
peerstate.degrade_event = 0i32;
|
||||||
dc_key_unref((*peerstate).gossip_key);
|
|
||||||
(*peerstate).gossip_key = 0 as *mut dc_key_t;
|
|
||||||
dc_key_unref((*peerstate).verified_key);
|
|
||||||
(*peerstate).verified_key = 0 as *mut dc_key_t;
|
|
||||||
(*peerstate).degrade_event = 0i32;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO should return bool /rtn
|
// TODO should return bool /rtn
|
||||||
pub unsafe fn dc_apeerstate_init_from_header(
|
pub unsafe fn dc_apeerstate_init_from_header(
|
||||||
mut peerstate: *mut dc_apeerstate_t,
|
peerstate: &mut dc_apeerstate_t,
|
||||||
header: &Aheader,
|
header: &Aheader,
|
||||||
message_time: time_t,
|
message_time: time_t,
|
||||||
) -> libc::c_int {
|
) -> libc::c_int {
|
||||||
if peerstate.is_null() {
|
|
||||||
return 0i32;
|
|
||||||
}
|
|
||||||
dc_apeerstate_empty(peerstate);
|
dc_apeerstate_empty(peerstate);
|
||||||
(*peerstate).addr = dc_strdup(CString::new(header.addr.clone()).unwrap().as_ptr());
|
peerstate.addr = dc_strdup(CString::new(header.addr.clone()).unwrap().as_ptr());
|
||||||
(*peerstate).last_seen = message_time;
|
peerstate.last_seen = message_time;
|
||||||
(*peerstate).last_seen_autocrypt = message_time;
|
peerstate.last_seen_autocrypt = message_time;
|
||||||
(*peerstate).to_save |= 0x2i32;
|
peerstate.to_save |= 0x2i32;
|
||||||
(*peerstate).prefer_encrypt = header.prefer_encrypt.to_i32().unwrap();
|
peerstate.prefer_encrypt = header.prefer_encrypt.to_i32().unwrap();
|
||||||
(*peerstate).public_key = dc_key_new();
|
peerstate.public_key = Some(header.public_key.clone());
|
||||||
dc_key_set_from_key((*peerstate).public_key, header.public_key);
|
|
||||||
dc_apeerstate_recalc_fingerprint(peerstate);
|
dc_apeerstate_recalc_fingerprint(peerstate);
|
||||||
|
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO should return bool /rtn
|
// TODO should return bool /rtn
|
||||||
pub unsafe fn dc_apeerstate_recalc_fingerprint(mut peerstate: *mut dc_apeerstate_t) -> libc::c_int {
|
pub unsafe fn dc_apeerstate_recalc_fingerprint(peerstate: &mut dc_apeerstate_t) -> libc::c_int {
|
||||||
let mut success: libc::c_int = 0i32;
|
let mut success: libc::c_int = 0i32;
|
||||||
let mut old_public_fingerprint: *mut libc::c_char = 0 as *mut libc::c_char;
|
let mut old_public_fingerprint: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||||
let mut old_gossip_fingerprint: *mut libc::c_char = 0 as *mut libc::c_char;
|
let mut old_gossip_fingerprint: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||||
if !peerstate.is_null() {
|
|
||||||
if !(*peerstate).public_key.is_null() {
|
if let Some(public_key) = peerstate.public_key {
|
||||||
old_public_fingerprint = (*peerstate).public_key_fingerprint;
|
old_public_fingerprint = peerstate.public_key_fingerprint;
|
||||||
(*peerstate).public_key_fingerprint =
|
peerstate.public_key_fingerprint = public_key.fingerprint_c();
|
||||||
dc_key_get_fingerprint((*peerstate).context, (*peerstate).public_key);
|
if old_public_fingerprint.is_null()
|
||||||
if old_public_fingerprint.is_null()
|
|| *old_public_fingerprint.offset(0isize) as libc::c_int == 0i32
|
||||||
|| *old_public_fingerprint.offset(0isize) as libc::c_int == 0i32
|
|| peerstate.public_key_fingerprint.is_null()
|
||||||
|| (*peerstate).public_key_fingerprint.is_null()
|
|| *peerstate.public_key_fingerprint.offset(0isize) as libc::c_int == 0i32
|
||||||
|| *(*peerstate).public_key_fingerprint.offset(0isize) as libc::c_int == 0i32
|
|| strcasecmp(old_public_fingerprint, peerstate.public_key_fingerprint) != 0i32
|
||||||
|| strcasecmp(old_public_fingerprint, (*peerstate).public_key_fingerprint) != 0i32
|
{
|
||||||
|
peerstate.to_save |= 0x2i32;
|
||||||
|
if !old_public_fingerprint.is_null()
|
||||||
|
&& 0 != *old_public_fingerprint.offset(0isize) as libc::c_int
|
||||||
{
|
{
|
||||||
(*peerstate).to_save |= 0x2i32;
|
peerstate.degrade_event |= 0x2i32;
|
||||||
if !old_public_fingerprint.is_null()
|
|
||||||
&& 0 != *old_public_fingerprint.offset(0isize) as libc::c_int
|
|
||||||
{
|
|
||||||
(*peerstate).degrade_event |= 0x2i32
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !(*peerstate).gossip_key.is_null() {
|
|
||||||
old_gossip_fingerprint = (*peerstate).gossip_key_fingerprint;
|
|
||||||
(*peerstate).gossip_key_fingerprint =
|
|
||||||
dc_key_get_fingerprint((*peerstate).context, (*peerstate).gossip_key);
|
|
||||||
if old_gossip_fingerprint.is_null()
|
|
||||||
|| *old_gossip_fingerprint.offset(0isize) as libc::c_int == 0i32
|
|
||||||
|| (*peerstate).gossip_key_fingerprint.is_null()
|
|
||||||
|| *(*peerstate).gossip_key_fingerprint.offset(0isize) as libc::c_int == 0i32
|
|
||||||
|| strcasecmp(old_gossip_fingerprint, (*peerstate).gossip_key_fingerprint) != 0i32
|
|
||||||
{
|
|
||||||
(*peerstate).to_save |= 0x2i32;
|
|
||||||
if !old_gossip_fingerprint.is_null()
|
|
||||||
&& 0 != *old_gossip_fingerprint.offset(0isize) as libc::c_int
|
|
||||||
{
|
|
||||||
(*peerstate).degrade_event |= 0x2i32
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
success = 1i32
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(gossip_key) = peerstate.gossip_key {
|
||||||
|
old_gossip_fingerprint = peerstate.gossip_key_fingerprint;
|
||||||
|
peerstate.gossip_key_fingerprint = gossip_key.fingerprint_c();
|
||||||
|
|
||||||
|
if old_gossip_fingerprint.is_null()
|
||||||
|
|| *old_gossip_fingerprint.offset(0isize) as libc::c_int == 0i32
|
||||||
|
|| peerstate.gossip_key_fingerprint.is_null()
|
||||||
|
|| *peerstate.gossip_key_fingerprint.offset(0isize) as libc::c_int == 0i32
|
||||||
|
|| strcasecmp(old_gossip_fingerprint, peerstate.gossip_key_fingerprint) != 0i32
|
||||||
|
{
|
||||||
|
peerstate.to_save |= 0x2i32;
|
||||||
|
if !old_gossip_fingerprint.is_null()
|
||||||
|
&& 0 != *old_gossip_fingerprint.offset(0isize) as libc::c_int
|
||||||
|
{
|
||||||
|
peerstate.degrade_event |= 0x2i32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
success = 1i32;
|
||||||
|
|
||||||
free(old_public_fingerprint as *mut libc::c_void);
|
free(old_public_fingerprint as *mut libc::c_void);
|
||||||
free(old_gossip_fingerprint as *mut libc::c_void);
|
free(old_gossip_fingerprint as *mut libc::c_void);
|
||||||
|
|
||||||
@@ -157,19 +154,15 @@ pub unsafe fn dc_apeerstate_recalc_fingerprint(mut peerstate: *mut dc_apeerstate
|
|||||||
|
|
||||||
// TODO should return bool /rtn
|
// TODO should return bool /rtn
|
||||||
pub unsafe fn dc_apeerstate_init_from_gossip(
|
pub unsafe fn dc_apeerstate_init_from_gossip(
|
||||||
mut peerstate: *mut dc_apeerstate_t,
|
peerstate: &mut dc_apeerstate_t,
|
||||||
gossip_header: &Aheader,
|
gossip_header: &Aheader,
|
||||||
message_time: time_t,
|
message_time: time_t,
|
||||||
) -> libc::c_int {
|
) -> libc::c_int {
|
||||||
if peerstate.is_null() {
|
|
||||||
return 0i32;
|
|
||||||
}
|
|
||||||
dc_apeerstate_empty(peerstate);
|
dc_apeerstate_empty(peerstate);
|
||||||
(*peerstate).addr = dc_strdup(CString::new(gossip_header.addr.clone()).unwrap().as_ptr());
|
peerstate.addr = dc_strdup(CString::new(gossip_header.addr.clone()).unwrap().as_ptr());
|
||||||
(*peerstate).gossip_timestamp = message_time;
|
peerstate.gossip_timestamp = message_time;
|
||||||
(*peerstate).to_save |= 0x2i32;
|
peerstate.to_save |= 0x2i32;
|
||||||
(*peerstate).gossip_key = dc_key_new();
|
peerstate.gossip_key = Some(gossip_header.public_key.clone());
|
||||||
dc_key_set_from_key((*peerstate).gossip_key, gossip_header.public_key);
|
|
||||||
dc_apeerstate_recalc_fingerprint(peerstate);
|
dc_apeerstate_recalc_fingerprint(peerstate);
|
||||||
|
|
||||||
1
|
1
|
||||||
@@ -177,31 +170,26 @@ pub unsafe fn dc_apeerstate_init_from_gossip(
|
|||||||
|
|
||||||
// TODO should return bool /rtn
|
// TODO should return bool /rtn
|
||||||
pub unsafe fn dc_apeerstate_degrade_encryption(
|
pub unsafe fn dc_apeerstate_degrade_encryption(
|
||||||
mut peerstate: *mut dc_apeerstate_t,
|
peerstate: &mut dc_apeerstate_t,
|
||||||
message_time: time_t,
|
message_time: time_t,
|
||||||
) -> libc::c_int {
|
) -> libc::c_int {
|
||||||
if peerstate.is_null() {
|
if peerstate.prefer_encrypt == 1i32 {
|
||||||
return 0i32;
|
peerstate.degrade_event |= 0x1i32
|
||||||
}
|
}
|
||||||
if (*peerstate).prefer_encrypt == 1i32 {
|
peerstate.prefer_encrypt = 20i32;
|
||||||
(*peerstate).degrade_event |= 0x1i32
|
peerstate.last_seen = message_time;
|
||||||
}
|
peerstate.to_save |= 0x2i32;
|
||||||
(*peerstate).prefer_encrypt = 20i32;
|
|
||||||
(*peerstate).last_seen = message_time;
|
|
||||||
(*peerstate).to_save |= 0x2i32;
|
|
||||||
|
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn dc_apeerstate_apply_header(
|
pub unsafe fn dc_apeerstate_apply_header(
|
||||||
mut peerstate: *mut dc_apeerstate_t,
|
peerstate: &mut dc_apeerstate_t,
|
||||||
header: &Aheader,
|
header: &Aheader,
|
||||||
message_time: time_t,
|
message_time: time_t,
|
||||||
) {
|
) {
|
||||||
if peerstate.is_null()
|
if peerstate.addr.is_null()
|
||||||
|| (*peerstate).addr.is_null()
|
|| CStr::from_ptr(peerstate.addr)
|
||||||
|| (*header.public_key).binary.is_null()
|
|
||||||
|| CStr::from_ptr((*peerstate).addr)
|
|
||||||
.to_str()
|
.to_str()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.to_lowercase()
|
.to_lowercase()
|
||||||
@@ -209,42 +197,39 @@ pub unsafe fn dc_apeerstate_apply_header(
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if message_time > (*peerstate).last_seen_autocrypt {
|
|
||||||
(*peerstate).last_seen = message_time;
|
if message_time > peerstate.last_seen_autocrypt {
|
||||||
(*peerstate).last_seen_autocrypt = message_time;
|
peerstate.last_seen = message_time;
|
||||||
(*peerstate).to_save |= 0x1i32;
|
peerstate.last_seen_autocrypt = message_time;
|
||||||
|
peerstate.to_save |= 0x1i32;
|
||||||
if (header.prefer_encrypt == EncryptPreference::Mutual
|
if (header.prefer_encrypt == EncryptPreference::Mutual
|
||||||
|| header.prefer_encrypt == EncryptPreference::NoPreference)
|
|| header.prefer_encrypt == EncryptPreference::NoPreference)
|
||||||
&& header.prefer_encrypt.to_i32().unwrap() != (*peerstate).prefer_encrypt
|
&& header.prefer_encrypt.to_i32().unwrap() != peerstate.prefer_encrypt
|
||||||
{
|
{
|
||||||
if (*peerstate).prefer_encrypt == 1i32
|
if peerstate.prefer_encrypt == 1i32
|
||||||
&& header.prefer_encrypt != EncryptPreference::Mutual
|
&& header.prefer_encrypt != EncryptPreference::Mutual
|
||||||
{
|
{
|
||||||
(*peerstate).degrade_event |= 0x1i32
|
peerstate.degrade_event |= 0x1i32
|
||||||
}
|
}
|
||||||
(*peerstate).prefer_encrypt = header.prefer_encrypt.to_i32().unwrap();
|
peerstate.prefer_encrypt = header.prefer_encrypt.to_i32().unwrap();
|
||||||
(*peerstate).to_save |= 0x2i32
|
peerstate.to_save |= 0x2i32
|
||||||
}
|
}
|
||||||
if (*peerstate).public_key.is_null() {
|
|
||||||
(*peerstate).public_key = dc_key_new()
|
if peerstate.public_key == Some(header.public_key) {
|
||||||
}
|
peerstate.public_key = Some(header.public_key);
|
||||||
if 0 == dc_key_equals((*peerstate).public_key, (*header).public_key) {
|
|
||||||
dc_key_set_from_key((*peerstate).public_key, (*header).public_key);
|
|
||||||
dc_apeerstate_recalc_fingerprint(peerstate);
|
dc_apeerstate_recalc_fingerprint(peerstate);
|
||||||
(*peerstate).to_save |= 0x2i32
|
peerstate.to_save |= 0x2i32;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn dc_apeerstate_apply_gossip(
|
pub unsafe fn dc_apeerstate_apply_gossip(
|
||||||
mut peerstate: *mut dc_apeerstate_t,
|
peerstate: &mut dc_apeerstate_t,
|
||||||
gossip_header: &Aheader,
|
gossip_header: &Aheader,
|
||||||
message_time: time_t,
|
message_time: time_t,
|
||||||
) {
|
) {
|
||||||
if peerstate.is_null()
|
if peerstate.addr.is_null()
|
||||||
|| (*peerstate).addr.is_null()
|
|| CStr::from_ptr(peerstate.addr)
|
||||||
|| (*(*gossip_header).public_key).binary.is_null()
|
|
||||||
|| CStr::from_ptr((*peerstate).addr)
|
|
||||||
.to_str()
|
.to_str()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.to_lowercase()
|
.to_lowercase()
|
||||||
@@ -252,93 +237,86 @@ pub unsafe fn dc_apeerstate_apply_gossip(
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if message_time > (*peerstate).gossip_timestamp {
|
|
||||||
(*peerstate).gossip_timestamp = message_time;
|
if message_time > peerstate.gossip_timestamp {
|
||||||
(*peerstate).to_save |= 0x1i32;
|
peerstate.gossip_timestamp = message_time;
|
||||||
if (*peerstate).gossip_key.is_null() {
|
peerstate.to_save |= 0x1i32;
|
||||||
(*peerstate).gossip_key = dc_key_new()
|
if peerstate.gossip_key == Some(gossip_header.public_key) {
|
||||||
}
|
peerstate.gossip_key = Some(gossip_header.public_key.clone());
|
||||||
if 0 == dc_key_equals((*peerstate).gossip_key, (*gossip_header).public_key) {
|
|
||||||
dc_key_set_from_key((*peerstate).gossip_key, (*gossip_header).public_key);
|
|
||||||
dc_apeerstate_recalc_fingerprint(peerstate);
|
dc_apeerstate_recalc_fingerprint(peerstate);
|
||||||
(*peerstate).to_save |= 0x2i32
|
peerstate.to_save |= 0x2i32
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn dc_apeerstate_render_gossip_header(
|
pub unsafe fn dc_apeerstate_render_gossip_header(
|
||||||
peerstate: *const dc_apeerstate_t,
|
peerstate: &dc_apeerstate_t,
|
||||||
min_verified: libc::c_int,
|
min_verified: libc::c_int,
|
||||||
) -> *mut libc::c_char {
|
) -> *mut libc::c_char {
|
||||||
if !(peerstate.is_null() || (*peerstate).addr.is_null()) {
|
if peerstate.addr.is_null() {
|
||||||
let addr = CStr::from_ptr((*peerstate).addr).to_str().unwrap().into();
|
return std::ptr::null_mut();
|
||||||
let key = dc_key_ref(dc_apeerstate_peek_key(peerstate, min_verified));
|
|
||||||
let header = Aheader::new(addr, key, EncryptPreference::NoPreference);
|
|
||||||
let rendered = header.to_string();
|
|
||||||
let rendered_c = CString::new(rendered).unwrap();
|
|
||||||
|
|
||||||
libc::strdup(rendered_c.as_ptr())
|
|
||||||
} else {
|
|
||||||
std::ptr::null_mut()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let addr = CStr::from_ptr(peerstate.addr).to_str().unwrap().into();
|
||||||
|
let key = dc_apeerstate_peek_key(peerstate, min_verified).clone();
|
||||||
|
let header = Aheader::new(addr, key, EncryptPreference::NoPreference);
|
||||||
|
let rendered = header.to_string();
|
||||||
|
let rendered_c = CString::new(rendered).unwrap();
|
||||||
|
|
||||||
|
libc::strdup(rendered_c.as_ptr())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn dc_apeerstate_peek_key(
|
pub unsafe fn dc_apeerstate_peek_key<'a>(
|
||||||
peerstate: *const dc_apeerstate_t,
|
peerstate: &dc_apeerstate_t<'a>,
|
||||||
min_verified: libc::c_int,
|
min_verified: libc::c_int,
|
||||||
) -> *mut dc_key_t {
|
) -> Option<&'a Key> {
|
||||||
if peerstate.is_null()
|
if peerstate.public_key.is_none()
|
||||||
|| !(*peerstate).public_key.is_null()
|
&& !peerstate.gossip_key.is_none()
|
||||||
&& ((*(*peerstate).public_key).binary.is_null()
|
&& !peerstate.verified_key.is_none()
|
||||||
|| (*(*peerstate).public_key).bytes <= 0i32)
|
|
||||||
|| !(*peerstate).gossip_key.is_null()
|
|
||||||
&& ((*(*peerstate).gossip_key).binary.is_null()
|
|
||||||
|| (*(*peerstate).gossip_key).bytes <= 0i32)
|
|
||||||
|| !(*peerstate).verified_key.is_null()
|
|
||||||
&& ((*(*peerstate).verified_key).binary.is_null()
|
|
||||||
|| (*(*peerstate).verified_key).bytes <= 0i32)
|
|
||||||
{
|
{
|
||||||
return 0 as *mut dc_key_t;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
if 0 != min_verified {
|
if 0 != min_verified {
|
||||||
return (*peerstate).verified_key;
|
return peerstate.verified_key.as_ref();
|
||||||
}
|
}
|
||||||
if !(*peerstate).public_key.is_null() {
|
if !peerstate.public_key.is_none() {
|
||||||
return (*peerstate).public_key;
|
return peerstate.public_key.as_ref();
|
||||||
}
|
}
|
||||||
(*peerstate).gossip_key
|
|
||||||
|
peerstate.gossip_key.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO should return bool /rtn
|
// TODO should return bool /rtn
|
||||||
pub unsafe fn dc_apeerstate_set_verified(
|
pub unsafe fn dc_apeerstate_set_verified(
|
||||||
mut peerstate: *mut dc_apeerstate_t,
|
peerstate: &mut dc_apeerstate_t,
|
||||||
which_key: libc::c_int,
|
which_key: libc::c_int,
|
||||||
fingerprint: *const libc::c_char,
|
fingerprint: *const libc::c_char,
|
||||||
verified: libc::c_int,
|
verified: libc::c_int,
|
||||||
) -> libc::c_int {
|
) -> libc::c_int {
|
||||||
let mut success: libc::c_int = 0i32;
|
let mut success: libc::c_int = 0;
|
||||||
if !(peerstate.is_null() || which_key != 0i32 && which_key != 1i32 || verified != 2i32) {
|
if !(which_key != 0 && which_key != 1 || verified != 2) {
|
||||||
if which_key == 1i32
|
if which_key == 1
|
||||||
&& !(*peerstate).public_key_fingerprint.is_null()
|
&& !peerstate.public_key_fingerprint.is_null()
|
||||||
&& *(*peerstate).public_key_fingerprint.offset(0isize) as libc::c_int != 0i32
|
&& *peerstate.public_key_fingerprint.offset(0isize) as libc::c_int != 0
|
||||||
&& *fingerprint.offset(0isize) as libc::c_int != 0i32
|
&& *fingerprint.offset(0isize) as libc::c_int != 0
|
||||||
&& strcasecmp((*peerstate).public_key_fingerprint, fingerprint) == 0i32
|
&& strcasecmp(peerstate.public_key_fingerprint, fingerprint) == 0
|
||||||
{
|
{
|
||||||
(*peerstate).to_save |= 0x2i32;
|
peerstate.to_save |= 0x2;
|
||||||
(*peerstate).verified_key = dc_key_ref((*peerstate).public_key);
|
peerstate.verified_key = Some(peerstate.public_key.clone());
|
||||||
(*peerstate).verified_key_fingerprint = dc_strdup((*peerstate).public_key_fingerprint);
|
peerstate.verified_key_fingerprint = dc_strdup(peerstate.public_key_fingerprint);
|
||||||
success = 1i32
|
success = 1
|
||||||
}
|
}
|
||||||
if which_key == 0i32
|
if which_key == 0
|
||||||
&& !(*peerstate).gossip_key_fingerprint.is_null()
|
&& !peerstate.gossip_key_fingerprint.is_null()
|
||||||
&& *(*peerstate).gossip_key_fingerprint.offset(0isize) as libc::c_int != 0i32
|
&& *peerstate.gossip_key_fingerprint.offset(0isize) as libc::c_int != 0
|
||||||
&& *fingerprint.offset(0isize) as libc::c_int != 0i32
|
&& *fingerprint.offset(0isize) as libc::c_int != 0
|
||||||
&& strcasecmp((*peerstate).gossip_key_fingerprint, fingerprint) == 0i32
|
&& strcasecmp(peerstate.gossip_key_fingerprint, fingerprint) == 0
|
||||||
{
|
{
|
||||||
(*peerstate).to_save |= 0x2i32;
|
peerstate.to_save |= 0x2;
|
||||||
(*peerstate).verified_key = dc_key_ref((*peerstate).gossip_key);
|
peerstate.verified_key = Some(peerstate.gossip_key.clone());
|
||||||
(*peerstate).verified_key_fingerprint = dc_strdup((*peerstate).gossip_key_fingerprint);
|
peerstate.verified_key_fingerprint = dc_strdup(peerstate.gossip_key_fingerprint);
|
||||||
success = 1i32
|
success = 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -347,24 +325,24 @@ pub unsafe fn dc_apeerstate_set_verified(
|
|||||||
|
|
||||||
// TODO should return bool /rtn
|
// TODO should return bool /rtn
|
||||||
pub unsafe fn dc_apeerstate_load_by_addr(
|
pub unsafe fn dc_apeerstate_load_by_addr(
|
||||||
peerstate: *mut dc_apeerstate_t,
|
peerstate: &mut dc_apeerstate_t,
|
||||||
sql: &dc_sqlite3_t,
|
sql: &dc_sqlite3_t,
|
||||||
addr: *const libc::c_char,
|
addr: *const libc::c_char,
|
||||||
) -> libc::c_int {
|
) -> libc::c_int {
|
||||||
let mut success: libc::c_int = 0i32;
|
let mut success: libc::c_int = 0;
|
||||||
let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt;
|
let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt;
|
||||||
if !(peerstate.is_null() || addr.is_null()) {
|
if !addr.is_null() {
|
||||||
dc_apeerstate_empty(peerstate);
|
dc_apeerstate_empty(peerstate);
|
||||||
stmt =
|
stmt =
|
||||||
dc_sqlite3_prepare(
|
dc_sqlite3_prepare(
|
||||||
(*peerstate).context,
|
peerstate.context,
|
||||||
sql,
|
sql,
|
||||||
b"SELECT addr, last_seen, last_seen_autocrypt, prefer_encrypted, public_key, gossip_timestamp, gossip_key, public_key_fingerprint, gossip_key_fingerprint, verified_key, verified_key_fingerprint FROM acpeerstates WHERE addr=? COLLATE NOCASE;\x00"
|
b"SELECT addr, last_seen, last_seen_autocrypt, prefer_encrypted, public_key, gossip_timestamp, gossip_key, public_key_fingerprint, gossip_key_fingerprint, verified_key, verified_key_fingerprint FROM acpeerstates WHERE addr=? COLLATE NOCASE;\x00"
|
||||||
as *const u8 as *const libc::c_char);
|
as *const u8 as *const libc::c_char);
|
||||||
sqlite3_bind_text(stmt, 1i32, addr, -1i32, None);
|
sqlite3_bind_text(stmt, 1, addr, -1, None);
|
||||||
if !(sqlite3_step(stmt) != 100i32) {
|
if !(sqlite3_step(stmt) != 100) {
|
||||||
dc_apeerstate_set_from_stmt(peerstate, stmt);
|
dc_apeerstate_set_from_stmt(peerstate, stmt);
|
||||||
success = 1i32
|
success = 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sqlite3_finalize(stmt);
|
sqlite3_finalize(stmt);
|
||||||
@@ -372,56 +350,52 @@ pub unsafe fn dc_apeerstate_load_by_addr(
|
|||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn dc_apeerstate_set_from_stmt(
|
unsafe fn dc_apeerstate_set_from_stmt(
|
||||||
mut peerstate: *mut dc_apeerstate_t,
|
mut peerstate: &mut dc_apeerstate_t,
|
||||||
stmt: *mut sqlite3_stmt,
|
stmt: *mut sqlite3_stmt,
|
||||||
) {
|
) {
|
||||||
(*peerstate).addr = dc_strdup(sqlite3_column_text(stmt, 0i32) as *mut libc::c_char);
|
peerstate.addr = dc_strdup(sqlite3_column_text(stmt, 0) as *mut libc::c_char);
|
||||||
(*peerstate).last_seen = sqlite3_column_int64(stmt, 1i32) as time_t;
|
peerstate.last_seen = sqlite3_column_int64(stmt, 1) as time_t;
|
||||||
(*peerstate).last_seen_autocrypt = sqlite3_column_int64(stmt, 2i32) as time_t;
|
peerstate.last_seen_autocrypt = sqlite3_column_int64(stmt, 2) as time_t;
|
||||||
(*peerstate).prefer_encrypt = sqlite3_column_int(stmt, 3i32);
|
peerstate.prefer_encrypt = sqlite3_column_int(stmt, 3);
|
||||||
(*peerstate).gossip_timestamp = sqlite3_column_int(stmt, 5i32) as time_t;
|
peerstate.gossip_timestamp = sqlite3_column_int(stmt, 5) as time_t;
|
||||||
(*peerstate).public_key_fingerprint =
|
peerstate.public_key_fingerprint = dc_strdup(sqlite3_column_text(stmt, 7) as *mut libc::c_char);
|
||||||
dc_strdup(sqlite3_column_text(stmt, 7i32) as *mut libc::c_char);
|
peerstate.gossip_key_fingerprint = dc_strdup(sqlite3_column_text(stmt, 8) as *mut libc::c_char);
|
||||||
(*peerstate).gossip_key_fingerprint =
|
peerstate.verified_key_fingerprint =
|
||||||
dc_strdup(sqlite3_column_text(stmt, 8i32) as *mut libc::c_char);
|
dc_strdup(sqlite3_column_text(stmt, 10) as *mut libc::c_char);
|
||||||
(*peerstate).verified_key_fingerprint =
|
|
||||||
dc_strdup(sqlite3_column_text(stmt, 10i32) as *mut libc::c_char);
|
if sqlite3_column_type(stmt, 4) != 5 {
|
||||||
if sqlite3_column_type(stmt, 4i32) != 5i32 {
|
peerstate.public_key = Key::from_stmt(stmt, 4, 0);
|
||||||
(*peerstate).public_key = dc_key_new();
|
|
||||||
dc_key_set_from_stmt((*peerstate).public_key, stmt, 4i32, 0i32);
|
|
||||||
}
|
}
|
||||||
if sqlite3_column_type(stmt, 6i32) != 5i32 {
|
if sqlite3_column_type(stmt, 6) != 5 {
|
||||||
(*peerstate).gossip_key = dc_key_new();
|
peerstate.gossip_key = Key::from_stmt(stmt, 6, 0);
|
||||||
dc_key_set_from_stmt((*peerstate).gossip_key, stmt, 6i32, 0i32);
|
}
|
||||||
|
if sqlite3_column_type(stmt, 9) != 5 {
|
||||||
|
peerstate.verified_key = Key::from_stmt(stmt, 9, 0);
|
||||||
}
|
}
|
||||||
if sqlite3_column_type(stmt, 9i32) != 5i32 {
|
|
||||||
(*peerstate).verified_key = dc_key_new();
|
|
||||||
dc_key_set_from_stmt((*peerstate).verified_key, stmt, 9i32, 0i32);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO should return bool /rtn
|
// TODO should return bool /rtn
|
||||||
pub unsafe fn dc_apeerstate_load_by_fingerprint(
|
pub unsafe fn dc_apeerstate_load_by_fingerprint(
|
||||||
peerstate: *mut dc_apeerstate_t,
|
peerstate: &mut dc_apeerstate_t,
|
||||||
sql: &dc_sqlite3_t,
|
sql: &dc_sqlite3_t,
|
||||||
fingerprint: *const libc::c_char,
|
fingerprint: *const libc::c_char,
|
||||||
) -> libc::c_int {
|
) -> libc::c_int {
|
||||||
let mut success: libc::c_int = 0i32;
|
let mut success: libc::c_int = 0;
|
||||||
let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt;
|
let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt;
|
||||||
if !(peerstate.is_null() || fingerprint.is_null()) {
|
if !fingerprint.is_null() {
|
||||||
dc_apeerstate_empty(peerstate);
|
dc_apeerstate_empty(peerstate);
|
||||||
stmt =
|
stmt =
|
||||||
dc_sqlite3_prepare(
|
dc_sqlite3_prepare(
|
||||||
(*peerstate).context,
|
peerstate.context,
|
||||||
sql,
|
sql,
|
||||||
b"SELECT addr, last_seen, last_seen_autocrypt, prefer_encrypted, public_key, gossip_timestamp, gossip_key, public_key_fingerprint, gossip_key_fingerprint, verified_key, verified_key_fingerprint FROM acpeerstates WHERE public_key_fingerprint=? COLLATE NOCASE OR gossip_key_fingerprint=? COLLATE NOCASE ORDER BY public_key_fingerprint=? DESC;\x00"
|
b"SELECT addr, last_seen, last_seen_autocrypt, prefer_encrypted, public_key, gossip_timestamp, gossip_key, public_key_fingerprint, gossip_key_fingerprint, verified_key, verified_key_fingerprint FROM acpeerstates WHERE public_key_fingerprint=? COLLATE NOCASE OR gossip_key_fingerprint=? COLLATE NOCASE ORDER BY public_key_fingerprint=? DESC;\x00"
|
||||||
as *const u8 as *const libc::c_char);
|
as *const u8 as *const libc::c_char);
|
||||||
sqlite3_bind_text(stmt, 1i32, fingerprint, -1i32, None);
|
sqlite3_bind_text(stmt, 1, fingerprint, -1, None);
|
||||||
sqlite3_bind_text(stmt, 2i32, fingerprint, -1i32, None);
|
sqlite3_bind_text(stmt, 2, fingerprint, -1, None);
|
||||||
sqlite3_bind_text(stmt, 3i32, fingerprint, -1i32, None);
|
sqlite3_bind_text(stmt, 3, fingerprint, -1, None);
|
||||||
if !(sqlite3_step(stmt) != 100i32) {
|
if sqlite3_step(stmt) == 100 {
|
||||||
dc_apeerstate_set_from_stmt(peerstate, stmt);
|
dc_apeerstate_set_from_stmt(peerstate, stmt);
|
||||||
success = 1i32
|
success = 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sqlite3_finalize(stmt);
|
sqlite3_finalize(stmt);
|
||||||
@@ -430,118 +404,104 @@ pub unsafe fn dc_apeerstate_load_by_fingerprint(
|
|||||||
|
|
||||||
// TODO should return bool /rtn
|
// TODO should return bool /rtn
|
||||||
pub unsafe fn dc_apeerstate_save_to_db(
|
pub unsafe fn dc_apeerstate_save_to_db(
|
||||||
peerstate: *const dc_apeerstate_t,
|
peerstate: &dc_apeerstate_t,
|
||||||
sql: &dc_sqlite3_t,
|
sql: &dc_sqlite3_t,
|
||||||
create: libc::c_int,
|
create: libc::c_int,
|
||||||
) -> libc::c_int {
|
) -> libc::c_int {
|
||||||
let current_block: u64;
|
let current_block: u64;
|
||||||
let mut success: libc::c_int = 0i32;
|
let mut success: libc::c_int = 0;
|
||||||
let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt;
|
let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt;
|
||||||
if peerstate.is_null() || (*peerstate).addr.is_null() {
|
if peerstate.addr.is_null() {
|
||||||
return 0i32;
|
return 0;
|
||||||
}
|
}
|
||||||
if 0 != create {
|
if 0 != create {
|
||||||
stmt = dc_sqlite3_prepare(
|
stmt = dc_sqlite3_prepare(
|
||||||
(*peerstate).context,
|
peerstate.context,
|
||||||
sql,
|
sql,
|
||||||
b"INSERT INTO acpeerstates (addr) VALUES(?);\x00" as *const u8 as *const libc::c_char,
|
b"INSERT INTO acpeerstates (addr) VALUES(?);\x00" as *const u8 as *const libc::c_char,
|
||||||
);
|
);
|
||||||
sqlite3_bind_text(stmt, 1i32, (*peerstate).addr, -1i32, None);
|
sqlite3_bind_text(stmt, 1, peerstate.addr, -1, None);
|
||||||
sqlite3_step(stmt);
|
sqlite3_step(stmt);
|
||||||
sqlite3_finalize(stmt);
|
sqlite3_finalize(stmt);
|
||||||
stmt = 0 as *mut sqlite3_stmt
|
stmt = 0 as *mut sqlite3_stmt
|
||||||
}
|
}
|
||||||
if 0 != (*peerstate).to_save & 0x2i32 || 0 != create {
|
if 0 != peerstate.to_save & 0x2 || 0 != create {
|
||||||
stmt =
|
stmt =
|
||||||
dc_sqlite3_prepare(
|
dc_sqlite3_prepare(
|
||||||
(*peerstate).context,sql,
|
peerstate.context,sql,
|
||||||
b"UPDATE acpeerstates SET last_seen=?, last_seen_autocrypt=?, prefer_encrypted=?, public_key=?, gossip_timestamp=?, gossip_key=?, public_key_fingerprint=?, gossip_key_fingerprint=?, verified_key=?, verified_key_fingerprint=? WHERE addr=?;\x00"
|
b"UPDATE acpeerstates SET last_seen=?, last_seen_autocrypt=?, prefer_encrypted=?, public_key=?, gossip_timestamp=?, gossip_key=?, public_key_fingerprint=?, gossip_key_fingerprint=?, verified_key=?, verified_key_fingerprint=? WHERE addr=?;\x00"
|
||||||
as *const u8 as *const libc::c_char);
|
as *const u8 as *const libc::c_char);
|
||||||
sqlite3_bind_int64(stmt, 1i32, (*peerstate).last_seen as sqlite3_int64);
|
sqlite3_bind_int64(stmt, 1, peerstate.last_seen as sqlite3_int64);
|
||||||
sqlite3_bind_int64(
|
sqlite3_bind_int64(stmt, 2, peerstate.last_seen_autocrypt as sqlite3_int64);
|
||||||
stmt,
|
sqlite3_bind_int64(stmt, 3, peerstate.prefer_encrypt as sqlite3_int64);
|
||||||
2i32,
|
|
||||||
(*peerstate).last_seen_autocrypt as sqlite3_int64,
|
|
||||||
);
|
|
||||||
sqlite3_bind_int64(stmt, 3i32, (*peerstate).prefer_encrypt as sqlite3_int64);
|
|
||||||
sqlite3_bind_blob(
|
sqlite3_bind_blob(
|
||||||
stmt,
|
stmt,
|
||||||
4i32,
|
4,
|
||||||
if !(*peerstate).public_key.is_null() {
|
if !peerstate.public_key.is_null() {
|
||||||
(*(*peerstate).public_key).binary
|
(*peerstate.public_key).binary
|
||||||
} else {
|
} else {
|
||||||
0 as *mut libc::c_void
|
0 as *mut libc::c_void
|
||||||
},
|
},
|
||||||
if !(*peerstate).public_key.is_null() {
|
if !peerstate.public_key.is_null() {
|
||||||
(*(*peerstate).public_key).bytes
|
(*peerstate.public_key).bytes
|
||||||
} else {
|
} else {
|
||||||
0i32
|
0
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
sqlite3_bind_int64(stmt, 5i32, (*peerstate).gossip_timestamp as sqlite3_int64);
|
sqlite3_bind_int64(stmt, 5, peerstate.gossip_timestamp as sqlite3_int64);
|
||||||
sqlite3_bind_blob(
|
sqlite3_bind_blob(
|
||||||
stmt,
|
stmt,
|
||||||
6i32,
|
6,
|
||||||
if !(*peerstate).gossip_key.is_null() {
|
if !peerstate.gossip_key.is_null() {
|
||||||
(*(*peerstate).gossip_key).binary
|
(*peerstate.gossip_key).binary
|
||||||
} else {
|
} else {
|
||||||
0 as *mut libc::c_void
|
0 as *mut libc::c_void
|
||||||
},
|
},
|
||||||
if !(*peerstate).gossip_key.is_null() {
|
if !peerstate.gossip_key.is_null() {
|
||||||
(*(*peerstate).gossip_key).bytes
|
(*peerstate.gossip_key).bytes
|
||||||
} else {
|
} else {
|
||||||
0i32
|
0
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
sqlite3_bind_text(stmt, 7i32, (*peerstate).public_key_fingerprint, -1i32, None);
|
sqlite3_bind_text(stmt, 7, peerstate.public_key_fingerprint, -1, None);
|
||||||
sqlite3_bind_text(stmt, 8i32, (*peerstate).gossip_key_fingerprint, -1i32, None);
|
sqlite3_bind_text(stmt, 8, peerstate.gossip_key_fingerprint, -1, None);
|
||||||
sqlite3_bind_blob(
|
sqlite3_bind_blob(
|
||||||
stmt,
|
stmt,
|
||||||
9i32,
|
9,
|
||||||
if !(*peerstate).verified_key.is_null() {
|
if !peerstate.verified_key.is_null() {
|
||||||
(*(*peerstate).verified_key).binary
|
(*peerstate.verified_key).binary
|
||||||
} else {
|
} else {
|
||||||
0 as *mut libc::c_void
|
0 as *mut libc::c_void
|
||||||
},
|
},
|
||||||
if !(*peerstate).verified_key.is_null() {
|
if !peerstate.verified_key.is_null() {
|
||||||
(*(*peerstate).verified_key).bytes
|
(*peerstate.verified_key).bytes
|
||||||
} else {
|
} else {
|
||||||
0i32
|
0
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
sqlite3_bind_text(
|
sqlite3_bind_text(stmt, 10, peerstate.verified_key_fingerprint, -1, None);
|
||||||
stmt,
|
sqlite3_bind_text(stmt, 11, peerstate.addr, -1, None);
|
||||||
10i32,
|
if sqlite3_step(stmt) != 101 {
|
||||||
(*peerstate).verified_key_fingerprint,
|
|
||||||
-1i32,
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
sqlite3_bind_text(stmt, 11i32, (*peerstate).addr, -1i32, None);
|
|
||||||
if sqlite3_step(stmt) != 101i32 {
|
|
||||||
current_block = 7258450500457619456;
|
current_block = 7258450500457619456;
|
||||||
} else {
|
} else {
|
||||||
sqlite3_finalize(stmt);
|
sqlite3_finalize(stmt);
|
||||||
stmt = 0 as *mut sqlite3_stmt;
|
stmt = 0 as *mut sqlite3_stmt;
|
||||||
current_block = 11913429853522160501;
|
current_block = 11913429853522160501;
|
||||||
}
|
}
|
||||||
} else if 0 != (*peerstate).to_save & 0x1i32 {
|
} else if 0 != peerstate.to_save & 0x1 {
|
||||||
stmt =
|
stmt =
|
||||||
dc_sqlite3_prepare(
|
dc_sqlite3_prepare(
|
||||||
(*peerstate).context,sql,
|
peerstate.context,sql,
|
||||||
b"UPDATE acpeerstates SET last_seen=?, last_seen_autocrypt=?, gossip_timestamp=? WHERE addr=?;\x00"
|
b"UPDATE acpeerstates SET last_seen=?, last_seen_autocrypt=?, gossip_timestamp=? WHERE addr=?;\x00"
|
||||||
as *const u8 as *const libc::c_char);
|
as *const u8 as *const libc::c_char);
|
||||||
sqlite3_bind_int64(stmt, 1i32, (*peerstate).last_seen as sqlite3_int64);
|
sqlite3_bind_int64(stmt, 1, peerstate.last_seen as sqlite3_int64);
|
||||||
sqlite3_bind_int64(
|
sqlite3_bind_int64(stmt, 2, peerstate.last_seen_autocrypt as sqlite3_int64);
|
||||||
stmt,
|
sqlite3_bind_int64(stmt, 3, peerstate.gossip_timestamp as sqlite3_int64);
|
||||||
2i32,
|
sqlite3_bind_text(stmt, 4, peerstate.addr, -1, None);
|
||||||
(*peerstate).last_seen_autocrypt as sqlite3_int64,
|
if sqlite3_step(stmt) != 101 {
|
||||||
);
|
|
||||||
sqlite3_bind_int64(stmt, 3i32, (*peerstate).gossip_timestamp as sqlite3_int64);
|
|
||||||
sqlite3_bind_text(stmt, 4i32, (*peerstate).addr, -1i32, None);
|
|
||||||
if sqlite3_step(stmt) != 101i32 {
|
|
||||||
current_block = 7258450500457619456;
|
current_block = 7258450500457619456;
|
||||||
} else {
|
} else {
|
||||||
sqlite3_finalize(stmt);
|
sqlite3_finalize(stmt);
|
||||||
@@ -553,10 +513,10 @@ pub unsafe fn dc_apeerstate_save_to_db(
|
|||||||
}
|
}
|
||||||
match current_block {
|
match current_block {
|
||||||
11913429853522160501 => {
|
11913429853522160501 => {
|
||||||
if 0 != (*peerstate).to_save & 0x2i32 || 0 != create {
|
if 0 != peerstate.to_save & 0x2 || 0 != create {
|
||||||
dc_reset_gossiped_timestamp((*peerstate).context, 0i32 as uint32_t);
|
dc_reset_gossiped_timestamp(peerstate.context, 0 as uint32_t);
|
||||||
}
|
}
|
||||||
success = 1i32
|
success = 1
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@@ -567,22 +527,22 @@ pub unsafe fn dc_apeerstate_save_to_db(
|
|||||||
|
|
||||||
// TODO should return bool /rtn
|
// TODO should return bool /rtn
|
||||||
pub unsafe fn dc_apeerstate_has_verified_key(
|
pub unsafe fn dc_apeerstate_has_verified_key(
|
||||||
peerstate: *const dc_apeerstate_t,
|
peerstate: &dc_apeerstate_t,
|
||||||
fingerprints: *const dc_hash_t,
|
fingerprints: *const dc_hash_t,
|
||||||
) -> libc::c_int {
|
) -> libc::c_int {
|
||||||
if peerstate.is_null() || fingerprints.is_null() {
|
if fingerprints.is_null() {
|
||||||
return 0i32;
|
return 0;
|
||||||
}
|
}
|
||||||
if !(*peerstate).verified_key.is_null()
|
if !peerstate.verified_key.is_some()
|
||||||
&& !(*peerstate).verified_key_fingerprint.is_null()
|
&& !peerstate.verified_key_fingerprint.is_null()
|
||||||
&& !dc_hash_find(
|
&& !dc_hash_find(
|
||||||
fingerprints,
|
fingerprints,
|
||||||
(*peerstate).verified_key_fingerprint as *const libc::c_void,
|
peerstate.verified_key_fingerprint as *const libc::c_void,
|
||||||
strlen((*peerstate).verified_key_fingerprint) as libc::c_int,
|
strlen(peerstate.verified_key_fingerprint) as libc::c_int,
|
||||||
)
|
)
|
||||||
.is_null()
|
.is_null()
|
||||||
{
|
{
|
||||||
return 1i32;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
0
|
0
|
||||||
|
|||||||
@@ -769,8 +769,8 @@ pub unsafe fn dc_get_contact_encrinfo(
|
|||||||
let mut ret: dc_strbuilder_t;
|
let mut ret: dc_strbuilder_t;
|
||||||
let loginparam: *mut dc_loginparam_t = dc_loginparam_new();
|
let loginparam: *mut dc_loginparam_t = dc_loginparam_new();
|
||||||
let contact: *mut dc_contact_t = dc_contact_new(context);
|
let contact: *mut dc_contact_t = dc_contact_new(context);
|
||||||
let peerstate: *mut dc_apeerstate_t = dc_apeerstate_new(context);
|
let mut peerstate = dc_apeerstate_new(context);
|
||||||
let self_key: *mut dc_key_t = dc_key_new();
|
|
||||||
let mut fingerprint_self: *mut libc::c_char = 0 as *mut libc::c_char;
|
let mut fingerprint_self: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||||
let mut fingerprint_other_verified: *mut libc::c_char = 0 as *mut libc::c_char;
|
let mut fingerprint_other_verified: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||||
let mut fingerprint_other_unverified: *mut libc::c_char = 0 as *mut libc::c_char;
|
let mut fingerprint_other_unverified: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||||
@@ -785,7 +785,7 @@ pub unsafe fn dc_get_contact_encrinfo(
|
|||||||
dc_strbuilder_init(&mut ret, 0i32);
|
dc_strbuilder_init(&mut ret, 0i32);
|
||||||
if !(!dc_contact_load_from_db(contact, &context.sql.clone().read().unwrap(), contact_id)) {
|
if !(!dc_contact_load_from_db(contact, &context.sql.clone().read().unwrap(), contact_id)) {
|
||||||
dc_apeerstate_load_by_addr(
|
dc_apeerstate_load_by_addr(
|
||||||
peerstate,
|
&mut peerstate,
|
||||||
&context.sql.clone().read().unwrap(),
|
&context.sql.clone().read().unwrap(),
|
||||||
(*contact).addr,
|
(*contact).addr,
|
||||||
);
|
);
|
||||||
@@ -795,16 +795,14 @@ pub unsafe fn dc_get_contact_encrinfo(
|
|||||||
&context.sql.clone().read().unwrap(),
|
&context.sql.clone().read().unwrap(),
|
||||||
b"configured_\x00" as *const u8 as *const libc::c_char,
|
b"configured_\x00" as *const u8 as *const libc::c_char,
|
||||||
);
|
);
|
||||||
dc_key_load_self_public(
|
let mut self_key = Key::from_self_public(
|
||||||
context,
|
context,
|
||||||
self_key,
|
(*loginparam).addr & context.sql.clone().read().unwrap(),
|
||||||
(*loginparam).addr,
|
|
||||||
&context.sql.clone().read().unwrap(),
|
|
||||||
);
|
);
|
||||||
if !dc_apeerstate_peek_key(peerstate, 0i32).is_null() {
|
if !dc_apeerstate_peek_key(&peerstate, 0).is_null() {
|
||||||
p = dc_stock_str(
|
p = dc_stock_str(
|
||||||
context,
|
context,
|
||||||
if (*peerstate).prefer_encrypt == 1i32 {
|
if peerstate.prefer_encrypt == 1i32 {
|
||||||
34i32
|
34i32
|
||||||
} else {
|
} else {
|
||||||
25i32
|
25i32
|
||||||
@@ -812,11 +810,10 @@ pub unsafe fn dc_get_contact_encrinfo(
|
|||||||
);
|
);
|
||||||
dc_strbuilder_cat(&mut ret, p);
|
dc_strbuilder_cat(&mut ret, p);
|
||||||
free(p as *mut libc::c_void);
|
free(p as *mut libc::c_void);
|
||||||
if (*self_key).binary.is_null() {
|
if self_key.is_none() {
|
||||||
dc_ensure_secret_key_exists(context);
|
dc_ensure_secret_key_exists(context);
|
||||||
dc_key_load_self_public(
|
self_key = Key::from_self_public(
|
||||||
context,
|
context,
|
||||||
self_key,
|
|
||||||
(*loginparam).addr,
|
(*loginparam).addr,
|
||||||
&context.sql.clone().read().unwrap(),
|
&context.sql.clone().read().unwrap(),
|
||||||
);
|
);
|
||||||
@@ -826,12 +823,18 @@ pub unsafe fn dc_get_contact_encrinfo(
|
|||||||
dc_strbuilder_cat(&mut ret, p);
|
dc_strbuilder_cat(&mut ret, p);
|
||||||
free(p as *mut libc::c_void);
|
free(p as *mut libc::c_void);
|
||||||
dc_strbuilder_cat(&mut ret, b":\x00" as *const u8 as *const libc::c_char);
|
dc_strbuilder_cat(&mut ret, b":\x00" as *const u8 as *const libc::c_char);
|
||||||
fingerprint_self = dc_key_get_formatted_fingerprint(context, self_key);
|
|
||||||
fingerprint_other_verified =
|
fingerprint_self = self_key
|
||||||
dc_key_get_formatted_fingerprint(context, dc_apeerstate_peek_key(peerstate, 2i32));
|
.map(|k| k.formatted_fingerprint_c())
|
||||||
fingerprint_other_unverified =
|
.unwrap_or(std::ptr::null_mut());
|
||||||
dc_key_get_formatted_fingerprint(context, dc_apeerstate_peek_key(peerstate, 0i32));
|
fingerprint_other_verified = dc_apeerstate_peek_key(&peerstate, 2)
|
||||||
if strcmp((*loginparam).addr, (*peerstate).addr) < 0i32 {
|
.map
|
||||||
|
.map(|k| k.formatted_fingerprint_c())
|
||||||
|
.unwrap_or(std::ptr::null_mut());
|
||||||
|
fingerprint_other_unverified = dc_apeerstate_peek_key(&peerstate, 0)
|
||||||
|
.map(|k| k.formatted_fingerprint_c())
|
||||||
|
.unwrap_or(std::ptr::null_mut());
|
||||||
|
if strcmp((*loginparam).addr, peerstate.addr) < 0i32 {
|
||||||
cat_fingerprint(
|
cat_fingerprint(
|
||||||
&mut ret,
|
&mut ret,
|
||||||
(*loginparam).addr,
|
(*loginparam).addr,
|
||||||
@@ -840,14 +843,14 @@ pub unsafe fn dc_get_contact_encrinfo(
|
|||||||
);
|
);
|
||||||
cat_fingerprint(
|
cat_fingerprint(
|
||||||
&mut ret,
|
&mut ret,
|
||||||
(*peerstate).addr,
|
peerstate.addr,
|
||||||
fingerprint_other_verified,
|
fingerprint_other_verified,
|
||||||
fingerprint_other_unverified,
|
fingerprint_other_unverified,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
cat_fingerprint(
|
cat_fingerprint(
|
||||||
&mut ret,
|
&mut ret,
|
||||||
(*peerstate).addr,
|
peerstate.addr,
|
||||||
fingerprint_other_verified,
|
fingerprint_other_verified,
|
||||||
fingerprint_other_unverified,
|
fingerprint_other_unverified,
|
||||||
);
|
);
|
||||||
@@ -874,7 +877,7 @@ pub unsafe fn dc_get_contact_encrinfo(
|
|||||||
dc_apeerstate_unref(peerstate);
|
dc_apeerstate_unref(peerstate);
|
||||||
dc_contact_unref(contact);
|
dc_contact_unref(contact);
|
||||||
dc_loginparam_unref(loginparam);
|
dc_loginparam_unref(loginparam);
|
||||||
dc_key_unref(self_key);
|
|
||||||
free(fingerprint_self as *mut libc::c_void);
|
free(fingerprint_self as *mut libc::c_void);
|
||||||
free(fingerprint_other_verified as *mut libc::c_void);
|
free(fingerprint_other_verified as *mut libc::c_void);
|
||||||
free(fingerprint_other_unverified as *mut libc::c_void);
|
free(fingerprint_other_unverified as *mut libc::c_void);
|
||||||
|
|||||||
@@ -636,7 +636,6 @@ pub unsafe fn dc_get_info(context: &dc_context_t) -> *mut libc::c_char {
|
|||||||
let e2ee_enabled;
|
let e2ee_enabled;
|
||||||
let prv_key_cnt;
|
let prv_key_cnt;
|
||||||
let pub_key_cnt;
|
let pub_key_cnt;
|
||||||
let self_public = dc_key_new();
|
|
||||||
let rpgp_enabled = 1;
|
let rpgp_enabled = 1;
|
||||||
|
|
||||||
let mut ret = dc_strbuilder_t {
|
let mut ret = dc_strbuilder_t {
|
||||||
@@ -710,16 +709,15 @@ pub unsafe fn dc_get_info(context: &dc_context_t) -> *mut libc::c_char {
|
|||||||
sqlite3_step(stmt);
|
sqlite3_step(stmt);
|
||||||
pub_key_cnt = sqlite3_column_int(stmt, 0);
|
pub_key_cnt = sqlite3_column_int(stmt, 0);
|
||||||
sqlite3_finalize(stmt);
|
sqlite3_finalize(stmt);
|
||||||
if 0 != dc_key_load_self_public(
|
if let Some(key) =
|
||||||
context,
|
Key::from_self_public(context, (*l2).addr, &context.sql.clone().read().unwrap())
|
||||||
self_public,
|
{
|
||||||
(*l2).addr,
|
fingerprint_str = key.fingerprint_c();
|
||||||
&context.sql.clone().read().unwrap(),
|
|
||||||
) {
|
|
||||||
fingerprint_str = dc_key_get_fingerprint(context, self_public)
|
|
||||||
} else {
|
} else {
|
||||||
fingerprint_str = dc_strdup(b"<Not yet calculated>\x00" as *const u8 as *const libc::c_char)
|
fingerprint_str =
|
||||||
|
dc_strdup(b"<Not yet calculated>\x00" as *const u8 as *const libc::c_char);
|
||||||
}
|
}
|
||||||
|
|
||||||
l_readable_str = dc_loginparam_get_readable(l);
|
l_readable_str = dc_loginparam_get_readable(l);
|
||||||
l2_readable_str = dc_loginparam_get_readable(l2);
|
l2_readable_str = dc_loginparam_get_readable(l2);
|
||||||
inbox_watch = dc_sqlite3_get_config_int(
|
inbox_watch = dc_sqlite3_get_config_int(
|
||||||
@@ -858,7 +856,6 @@ pub unsafe fn dc_get_info(context: &dc_context_t) -> *mut libc::c_char {
|
|||||||
free(configured_sentbox_folder as *mut libc::c_void);
|
free(configured_sentbox_folder as *mut libc::c_void);
|
||||||
free(configured_mvbox_folder as *mut libc::c_void);
|
free(configured_mvbox_folder as *mut libc::c_void);
|
||||||
free(fingerprint_str as *mut libc::c_void);
|
free(fingerprint_str as *mut libc::c_void);
|
||||||
dc_key_unref(self_public);
|
|
||||||
|
|
||||||
ret.buf
|
ret.buf
|
||||||
}
|
}
|
||||||
|
|||||||
257
src/dc_e2ee.rs
257
src/dc_e2ee.rs
@@ -62,7 +62,6 @@ pub unsafe fn dc_e2ee_encrypt(
|
|||||||
/*just a pointer into mailmime structure, must not be freed*/
|
/*just a pointer into mailmime structure, must not be freed*/
|
||||||
let imffields_unprotected: *mut mailimf_fields;
|
let imffields_unprotected: *mut mailimf_fields;
|
||||||
let keyring: *mut dc_keyring_t = dc_keyring_new();
|
let keyring: *mut dc_keyring_t = dc_keyring_new();
|
||||||
let sign_key: *mut dc_key_t = dc_key_new();
|
|
||||||
let plain: *mut MMAPString = mmap_string_new(b"\x00" as *const u8 as *const libc::c_char);
|
let plain: *mut MMAPString = mmap_string_new(b"\x00" as *const u8 as *const libc::c_char);
|
||||||
let mut ctext: *mut libc::c_char = 0 as *mut libc::c_char;
|
let mut ctext: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||||
let mut ctext_bytes: size_t = 0i32 as size_t;
|
let mut ctext_bytes: size_t = 0i32 as size_t;
|
||||||
@@ -79,7 +78,6 @@ pub unsafe fn dc_e2ee_encrypt(
|
|||||||
|| in_out_message.is_null()
|
|| in_out_message.is_null()
|
||||||
|| !(*in_out_message).mm_parent.is_null()
|
|| !(*in_out_message).mm_parent.is_null()
|
||||||
|| keyring.is_null()
|
|| keyring.is_null()
|
||||||
|| sign_key.is_null()
|
|
||||||
|| plain.is_null()
|
|| plain.is_null()
|
||||||
|| helper.is_null())
|
|| helper.is_null())
|
||||||
{
|
{
|
||||||
@@ -103,9 +101,10 @@ pub unsafe fn dc_e2ee_encrypt(
|
|||||||
0 as *const libc::c_char,
|
0 as *const libc::c_char,
|
||||||
);
|
);
|
||||||
|
|
||||||
let public_key = dc_key_new();
|
|
||||||
if !addr.is_null() {
|
if !addr.is_null() {
|
||||||
if 0 != load_or_generate_self_public_key(context, public_key, addr, in_out_message) {
|
if let Some(public_key) =
|
||||||
|
load_or_generate_self_public_key(context, addr, in_out_message)
|
||||||
|
{
|
||||||
/*only for random-seed*/
|
/*only for random-seed*/
|
||||||
if prefer_encrypt == EncryptPreference::Mutual || 0 != e2ee_guaranteed {
|
if prefer_encrypt == EncryptPreference::Mutual || 0 != e2ee_guaranteed {
|
||||||
do_encrypt = 1i32;
|
do_encrypt = 1i32;
|
||||||
@@ -118,22 +117,22 @@ pub unsafe fn dc_e2ee_encrypt(
|
|||||||
0 as *mut libc::c_void
|
0 as *mut libc::c_void
|
||||||
})
|
})
|
||||||
as *const libc::c_char;
|
as *const libc::c_char;
|
||||||
let peerstate: *mut dc_apeerstate_t = dc_apeerstate_new(context);
|
let peerstate = dc_apeerstate_new(context);
|
||||||
let mut key_to_use: *mut dc_key_t = 0 as *mut dc_key_t;
|
|
||||||
if !(strcasecmp(recipient_addr, addr) == 0i32) {
|
if !(strcasecmp(recipient_addr, addr) == 0i32) {
|
||||||
if 0 != dc_apeerstate_load_by_addr(
|
if 0 != dc_apeerstate_load_by_addr(
|
||||||
peerstate,
|
peerstate,
|
||||||
&context.sql.clone().read().unwrap(),
|
&context.sql.clone().read().unwrap(),
|
||||||
recipient_addr,
|
recipient_addr,
|
||||||
) && {
|
) && (peerstate.prefer_encrypt == 1i32 || 0 != e2ee_guaranteed)
|
||||||
key_to_use = dc_apeerstate_peek_key(peerstate, min_verified);
|
|
||||||
!key_to_use.is_null()
|
|
||||||
} && ((*peerstate).prefer_encrypt == 1i32 || 0 != e2ee_guaranteed)
|
|
||||||
{
|
{
|
||||||
dc_keyring_add(keyring, key_to_use);
|
if let Some(key_to_use) =
|
||||||
dc_array_add_ptr(peerstates, peerstate as *mut libc::c_void);
|
dc_apeerstate_peek_key(peerstate, min_verified)
|
||||||
|
{
|
||||||
|
dc_keyring_add(keyring, key_to_use);
|
||||||
|
dc_array_add_ptr(peerstates, &peerstate);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
dc_apeerstate_unref(peerstate);
|
dc_apeerstate_unref(&mut peerstate);
|
||||||
do_encrypt = 0i32;
|
do_encrypt = 0i32;
|
||||||
/* if we cannot encrypt to a single recipient, we cannot encrypt the message at all */
|
/* if we cannot encrypt to a single recipient, we cannot encrypt the message at all */
|
||||||
break;
|
break;
|
||||||
@@ -146,17 +145,18 @@ pub unsafe fn dc_e2ee_encrypt(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if 0 != do_encrypt {
|
let sign_key = if 0 != do_encrypt {
|
||||||
dc_keyring_add(keyring, public_key);
|
dc_keyring_add(keyring, public_key);
|
||||||
if 0 == dc_key_load_self_private(
|
let key =
|
||||||
context,
|
Key::from_self_private(context, addr, &context.sql.clone().read().unwrap());
|
||||||
sign_key,
|
|
||||||
addr,
|
if key.is_none() {
|
||||||
&context.sql.clone().read().unwrap(),
|
do_encrypt = 0i32;
|
||||||
) {
|
|
||||||
do_encrypt = 0i32
|
|
||||||
}
|
}
|
||||||
}
|
key
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
if 0 != force_unencrypted {
|
if 0 != force_unencrypted {
|
||||||
do_encrypt = 0i32
|
do_encrypt = 0i32
|
||||||
}
|
}
|
||||||
@@ -309,7 +309,7 @@ pub unsafe fn dc_e2ee_encrypt(
|
|||||||
(*plain).str_0 as *const libc::c_void,
|
(*plain).str_0 as *const libc::c_void,
|
||||||
(*plain).len,
|
(*plain).len,
|
||||||
keyring,
|
keyring,
|
||||||
sign_key,
|
&sign_key,
|
||||||
1,
|
1,
|
||||||
&mut ctext as *mut *mut libc::c_char as *mut *mut libc::c_void,
|
&mut ctext as *mut *mut libc::c_char as *mut *mut libc::c_void,
|
||||||
&mut ctext_bytes,
|
&mut ctext_bytes,
|
||||||
@@ -389,7 +389,6 @@ pub unsafe fn dc_e2ee_encrypt(
|
|||||||
}
|
}
|
||||||
|
|
||||||
dc_keyring_unref(keyring);
|
dc_keyring_unref(keyring);
|
||||||
dc_key_unref(sign_key);
|
|
||||||
if !plain.is_null() {
|
if !plain.is_null() {
|
||||||
mmap_string_free(plain);
|
mmap_string_free(plain);
|
||||||
}
|
}
|
||||||
@@ -513,123 +512,87 @@ unsafe fn new_data_part(
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Generate Keypairs
|
* Generate Keypairs
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
// TODO should return bool /rtn
|
|
||||||
unsafe fn load_or_generate_self_public_key(
|
unsafe fn load_or_generate_self_public_key(
|
||||||
context: &dc_context_t,
|
context: &dc_context_t,
|
||||||
public_key: *mut dc_key_t,
|
|
||||||
self_addr: *const libc::c_char,
|
self_addr: *const libc::c_char,
|
||||||
random_data_mime: *mut mailmime,
|
random_data_mime: *mut mailmime,
|
||||||
) -> libc::c_int {
|
) -> Option<Key> {
|
||||||
let mut current_block: u64;
|
let mut current_block: u64;
|
||||||
/* avoid double creation (we unlock the database during creation) */
|
/* avoid double creation (we unlock the database during creation) */
|
||||||
static mut s_in_key_creation: libc::c_int = 0i32;
|
static mut s_in_key_creation: libc::c_int = 0i32;
|
||||||
let key_created: libc::c_int;
|
let key_created: libc::c_int;
|
||||||
let mut success: libc::c_int = 0i32;
|
let mut success: libc::c_int = 0i32;
|
||||||
let mut key_creation_here: libc::c_int = 0i32;
|
let mut key_creation_here: libc::c_int = 0i32;
|
||||||
if !public_key.is_null() {
|
|
||||||
if 0 == dc_key_load_self_public(
|
let mut key = Key::from_self_public(context, self_addr, &context.sql.clone().read().unwrap());
|
||||||
context,
|
if key.is_some() {
|
||||||
public_key,
|
return key;
|
||||||
self_addr,
|
|
||||||
&context.sql.clone().read().unwrap(),
|
|
||||||
) {
|
|
||||||
/* create the keypair - this may take a moment, however, as this is in a thread, this is no big deal */
|
|
||||||
if 0 != s_in_key_creation {
|
|
||||||
current_block = 10496152961502316708;
|
|
||||||
} else {
|
|
||||||
key_creation_here = 1i32;
|
|
||||||
s_in_key_creation = 1i32;
|
|
||||||
if !random_data_mime.is_null() {
|
|
||||||
let random_data_mmap: *mut MMAPString;
|
|
||||||
let mut col: libc::c_int = 0i32;
|
|
||||||
random_data_mmap = mmap_string_new(b"\x00" as *const u8 as *const libc::c_char);
|
|
||||||
if random_data_mmap.is_null() {
|
|
||||||
current_block = 10496152961502316708;
|
|
||||||
} else {
|
|
||||||
mailmime_write_mem(random_data_mmap, &mut col, random_data_mime);
|
|
||||||
mmap_string_free(random_data_mmap);
|
|
||||||
current_block = 26972500619410423;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
current_block = 26972500619410423;
|
|
||||||
}
|
|
||||||
match current_block {
|
|
||||||
10496152961502316708 => {}
|
|
||||||
_ => {
|
|
||||||
let private_key: *mut dc_key_t = dc_key_new();
|
|
||||||
let start: libc::clock_t = clock();
|
|
||||||
dc_log_info(
|
|
||||||
context,
|
|
||||||
0i32,
|
|
||||||
b"Generating keypair with %i bits, e=%i ...\x00" as *const u8
|
|
||||||
as *const libc::c_char,
|
|
||||||
2048i32,
|
|
||||||
65537i32,
|
|
||||||
);
|
|
||||||
key_created =
|
|
||||||
dc_pgp_create_keypair(context, self_addr, public_key, private_key);
|
|
||||||
if 0 == key_created {
|
|
||||||
dc_log_warning(
|
|
||||||
context,
|
|
||||||
0i32,
|
|
||||||
b"Cannot create keypair.\x00" as *const u8 as *const libc::c_char,
|
|
||||||
);
|
|
||||||
current_block = 10496152961502316708;
|
|
||||||
} else if 0 == dc_pgp_is_valid_key(context, public_key)
|
|
||||||
|| 0 == dc_pgp_is_valid_key(context, private_key)
|
|
||||||
{
|
|
||||||
dc_log_warning(
|
|
||||||
context,
|
|
||||||
0i32,
|
|
||||||
b"Generated keys are not valid.\x00" as *const u8
|
|
||||||
as *const libc::c_char,
|
|
||||||
);
|
|
||||||
current_block = 10496152961502316708;
|
|
||||||
} else if 0
|
|
||||||
== dc_key_save_self_keypair(
|
|
||||||
context,
|
|
||||||
public_key,
|
|
||||||
private_key,
|
|
||||||
self_addr,
|
|
||||||
1i32,
|
|
||||||
&context.sql.clone().read().unwrap(),
|
|
||||||
)
|
|
||||||
{
|
|
||||||
/*set default*/
|
|
||||||
dc_log_warning(
|
|
||||||
context,
|
|
||||||
0i32,
|
|
||||||
b"Cannot save keypair.\x00" as *const u8 as *const libc::c_char,
|
|
||||||
);
|
|
||||||
current_block = 10496152961502316708;
|
|
||||||
} else {
|
|
||||||
dc_log_info(
|
|
||||||
context,
|
|
||||||
0i32,
|
|
||||||
b"Keypair generated in %.3f s.\x00" as *const u8
|
|
||||||
as *const libc::c_char,
|
|
||||||
clock().wrapping_sub(start) as libc::c_double
|
|
||||||
/ 1000000i32 as libc::c_double,
|
|
||||||
);
|
|
||||||
dc_key_unref(private_key);
|
|
||||||
current_block = 1118134448028020070;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
current_block = 1118134448028020070;
|
|
||||||
}
|
|
||||||
match current_block {
|
|
||||||
10496152961502316708 => {}
|
|
||||||
_ => success = 1i32,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if 0 != key_creation_here {
|
|
||||||
s_in_key_creation = 0i32
|
|
||||||
}
|
}
|
||||||
|
|
||||||
success
|
/* create the keypair - this may take a moment, however, as this is in a thread, this is no big deal */
|
||||||
|
if 0 != s_in_key_creation {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
key_creation_here = 1;
|
||||||
|
s_in_key_creation = 1;
|
||||||
|
|
||||||
|
let start: libc::clock_t = clock();
|
||||||
|
dc_log_info(
|
||||||
|
context,
|
||||||
|
0i32,
|
||||||
|
b"Generating keypair with %i bits, e=%i ...\x00" as *const u8 as *const libc::c_char,
|
||||||
|
2048i32,
|
||||||
|
65537i32,
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Some((public_key, private_key)) = dc_pgp_create_keypair(context, self_addr) {
|
||||||
|
if 0 == dc_pgp_is_valid_key(context, &public_key)
|
||||||
|
|| 0 == dc_pgp_is_valid_key(context, &private_key)
|
||||||
|
{
|
||||||
|
dc_log_warning(
|
||||||
|
context,
|
||||||
|
0i32,
|
||||||
|
b"Generated keys are not valid.\x00" as *const u8 as *const libc::c_char,
|
||||||
|
);
|
||||||
|
} else if 0
|
||||||
|
== dc_key_save_self_keypair(
|
||||||
|
context,
|
||||||
|
&public_key,
|
||||||
|
&private_key,
|
||||||
|
self_addr,
|
||||||
|
1i32,
|
||||||
|
&context.sql.clone().read().unwrap(),
|
||||||
|
)
|
||||||
|
{
|
||||||
|
/*set default*/
|
||||||
|
dc_log_warning(
|
||||||
|
context,
|
||||||
|
0i32,
|
||||||
|
b"Cannot save keypair.\x00" as *const u8 as *const libc::c_char,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
dc_log_info(
|
||||||
|
context,
|
||||||
|
0i32,
|
||||||
|
b"Keypair generated in %.3f s.\x00" as *const u8 as *const libc::c_char,
|
||||||
|
clock().wrapping_sub(start) as libc::c_double / 1000000i32 as libc::c_double,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
key = public_key;
|
||||||
|
} else {
|
||||||
|
dc_log_warning(
|
||||||
|
context,
|
||||||
|
0i32,
|
||||||
|
b"Cannot create keypair.\x00" as *const u8 as *const libc::c_char,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if 0 != key_creation_here {
|
||||||
|
s_in_key_creation = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
key
|
||||||
}
|
}
|
||||||
|
|
||||||
/* returns 1 if sth. was decrypted, 0 in other cases */
|
/* returns 1 if sth. was decrypted, 0 in other cases */
|
||||||
@@ -1241,30 +1204,26 @@ pub unsafe fn dc_ensure_secret_key_exists(context: &dc_context_t) -> libc::c_int
|
|||||||
/* normally, the key is generated as soon as the first mail is send
|
/* normally, the key is generated as soon as the first mail is send
|
||||||
(this is to gain some extra-random-seed by the message content and the timespan between program start and message sending) */
|
(this is to gain some extra-random-seed by the message content and the timespan between program start and message sending) */
|
||||||
let mut success: libc::c_int = 0i32;
|
let mut success: libc::c_int = 0i32;
|
||||||
let public_key: *mut dc_key_t = dc_key_new();
|
|
||||||
let mut self_addr: *mut libc::c_char = 0 as *mut libc::c_char;
|
let mut self_addr: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||||
if !public_key.is_null() {
|
|
||||||
self_addr = dc_sqlite3_get_config(
|
self_addr = dc_sqlite3_get_config(
|
||||||
|
context,
|
||||||
|
&context.sql.clone().read().unwrap(),
|
||||||
|
b"configured_addr\x00" as *const u8 as *const libc::c_char,
|
||||||
|
0 as *const libc::c_char,
|
||||||
|
);
|
||||||
|
if self_addr.is_null() {
|
||||||
|
dc_log_warning(
|
||||||
context,
|
context,
|
||||||
&context.sql.clone().read().unwrap(),
|
0i32,
|
||||||
b"configured_addr\x00" as *const u8 as *const libc::c_char,
|
b"Cannot ensure secret key if context is not configured.\x00" as *const u8
|
||||||
0 as *const libc::c_char,
|
as *const libc::c_char,
|
||||||
);
|
);
|
||||||
if self_addr.is_null() {
|
} else if load_or_generate_self_public_key(context, self_addr, 0 as *mut mailmime).is_some() {
|
||||||
dc_log_warning(
|
/*no random text data for seeding available*/
|
||||||
context,
|
success = 1i32
|
||||||
0i32,
|
|
||||||
b"Cannot ensure secret key if context is not configured.\x00" as *const u8
|
|
||||||
as *const libc::c_char,
|
|
||||||
);
|
|
||||||
} else if !(0
|
|
||||||
== load_or_generate_self_public_key(context, public_key, self_addr, 0 as *mut mailmime))
|
|
||||||
{
|
|
||||||
/*no random text data for seeding available*/
|
|
||||||
success = 1i32
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
dc_key_unref(public_key);
|
|
||||||
free(self_addr as *mut libc::c_void);
|
free(self_addr as *mut libc::c_void);
|
||||||
|
|
||||||
success
|
success
|
||||||
|
|||||||
201
src/dc_imex.rs
201
src/dc_imex.rs
@@ -3,7 +3,7 @@ use mmime::mmapstring::*;
|
|||||||
use mmime::other::*;
|
use mmime::other::*;
|
||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
|
|
||||||
use crate::constants::Event;
|
use crate::constants::*;
|
||||||
use crate::dc_chat::*;
|
use crate::dc_chat::*;
|
||||||
use crate::dc_configure::*;
|
use crate::dc_configure::*;
|
||||||
use crate::dc_context::dc_context_t;
|
use crate::dc_context::dc_context_t;
|
||||||
@@ -288,11 +288,11 @@ pub unsafe extern "C" fn dc_render_setup_file(
|
|||||||
) -> *mut libc::c_char {
|
) -> *mut libc::c_char {
|
||||||
let stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt;
|
let stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt;
|
||||||
let mut self_addr: *mut libc::c_char = 0 as *mut libc::c_char;
|
let mut self_addr: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||||
let curr_private_key: *mut dc_key_t = dc_key_new();
|
|
||||||
let mut passphrase_begin: [libc::c_char; 8] = [0; 8];
|
let mut passphrase_begin: [libc::c_char; 8] = [0; 8];
|
||||||
let mut encr_string: *mut libc::c_char = 0 as *mut libc::c_char;
|
let mut encr_string: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||||
let mut ret_setupfilecontent: *mut libc::c_char = 0 as *mut libc::c_char;
|
let mut ret_setupfilecontent: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||||
if !(passphrase.is_null() || strlen(passphrase) < 2 || curr_private_key.is_null()) {
|
if !(passphrase.is_null() || strlen(passphrase) < 2) {
|
||||||
strncpy(passphrase_begin.as_mut_ptr(), passphrase, 2);
|
strncpy(passphrase_begin.as_mut_ptr(), passphrase, 2);
|
||||||
passphrase_begin[2usize] = 0i32 as libc::c_char;
|
passphrase_begin[2usize] = 0i32 as libc::c_char;
|
||||||
/* create the payload */
|
/* create the payload */
|
||||||
@@ -303,27 +303,22 @@ pub unsafe extern "C" fn dc_render_setup_file(
|
|||||||
b"configured_addr\x00" as *const u8 as *const libc::c_char,
|
b"configured_addr\x00" as *const u8 as *const libc::c_char,
|
||||||
0 as *const libc::c_char,
|
0 as *const libc::c_char,
|
||||||
);
|
);
|
||||||
dc_key_load_self_private(
|
let curr_private_key =
|
||||||
context,
|
Key::from_self_private(context, self_addr, &context.sql.clone().read().unwrap());
|
||||||
curr_private_key,
|
|
||||||
self_addr,
|
|
||||||
&context.sql.clone().read().unwrap(),
|
|
||||||
);
|
|
||||||
let e2ee_enabled: libc::c_int = dc_sqlite3_get_config_int(
|
let e2ee_enabled: libc::c_int = dc_sqlite3_get_config_int(
|
||||||
context,
|
context,
|
||||||
&context.sql.clone().read().unwrap(),
|
&context.sql.clone().read().unwrap(),
|
||||||
b"e2ee_enabled\x00" as *const u8 as *const libc::c_char,
|
b"e2ee_enabled\x00" as *const u8 as *const libc::c_char,
|
||||||
1i32,
|
1i32,
|
||||||
);
|
);
|
||||||
let payload_key_asc: *mut libc::c_char = dc_key_render_asc(
|
|
||||||
curr_private_key,
|
let headers = if 0 != e2ee_enabled {
|
||||||
if 0 != e2ee_enabled {
|
Some(("Autocrypt-Prefer-Encrypt", "mutual"))
|
||||||
Some(("Autocrypt-Prefer-Encrypt", "mutual"))
|
} else {
|
||||||
} else {
|
None
|
||||||
None
|
};
|
||||||
},
|
|
||||||
);
|
if let Some(payload_key_asc) = curr_private_key.map(|k| k.to_asc_c(headers)) {
|
||||||
if !payload_key_asc.is_null() {
|
|
||||||
if !(0
|
if !(0
|
||||||
== dc_pgp_symm_encrypt(
|
== dc_pgp_symm_encrypt(
|
||||||
context,
|
context,
|
||||||
@@ -368,7 +363,7 @@ pub unsafe extern "C" fn dc_render_setup_file(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
sqlite3_finalize(stmt);
|
sqlite3_finalize(stmt);
|
||||||
dc_key_unref(curr_private_key);
|
|
||||||
free(encr_string as *mut libc::c_void);
|
free(encr_string as *mut libc::c_void);
|
||||||
free(self_addr as *mut libc::c_void);
|
free(self_addr as *mut libc::c_void);
|
||||||
|
|
||||||
@@ -503,8 +498,6 @@ unsafe fn set_self_key(
|
|||||||
let mut buf_preferencrypt: *const libc::c_char = 0 as *const libc::c_char;
|
let mut buf_preferencrypt: *const libc::c_char = 0 as *const libc::c_char;
|
||||||
// - " -
|
// - " -
|
||||||
let mut buf_base64: *const libc::c_char = 0 as *const libc::c_char;
|
let mut buf_base64: *const libc::c_char = 0 as *const libc::c_char;
|
||||||
let private_key: *mut dc_key_t = dc_key_new();
|
|
||||||
let public_key: *mut dc_key_t = dc_key_new();
|
|
||||||
let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt;
|
let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt;
|
||||||
let mut self_addr: *mut libc::c_char = 0 as *mut libc::c_char;
|
let mut self_addr: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||||
buf = dc_strdup(armored);
|
buf = dc_strdup(armored);
|
||||||
@@ -525,93 +518,94 @@ unsafe fn set_self_key(
|
|||||||
0i32,
|
0i32,
|
||||||
b"File does not contain a private key.\x00" as *const u8 as *const libc::c_char,
|
b"File does not contain a private key.\x00" as *const u8 as *const libc::c_char,
|
||||||
);
|
);
|
||||||
} else if 0 == dc_key_set_from_base64(private_key, buf_base64, 1i32)
|
|
||||||
|| 0 == dc_pgp_is_valid_key(context, private_key)
|
|
||||||
|| 0 == dc_pgp_split_key(context, private_key, public_key)
|
|
||||||
{
|
|
||||||
dc_log_error(
|
|
||||||
context,
|
|
||||||
0i32,
|
|
||||||
b"File does not contain a valid private key.\x00" as *const u8 as *const libc::c_char,
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
stmt = dc_sqlite3_prepare(
|
if let Some((private_key, public_key)) = Key::from_base64(buf_base64, KeyType::Private)
|
||||||
context,
|
.and_then(|k| dc_pgp_split_key(context, &k).map(|pk| (k, pk)))
|
||||||
&context.sql.clone().read().unwrap(),
|
{
|
||||||
b"DELETE FROM keypairs WHERE public_key=? OR private_key=?;\x00" as *const u8
|
stmt = dc_sqlite3_prepare(
|
||||||
as *const libc::c_char,
|
|
||||||
);
|
|
||||||
sqlite3_bind_blob(stmt, 1i32, (*public_key).binary, (*public_key).bytes, None);
|
|
||||||
sqlite3_bind_blob(
|
|
||||||
stmt,
|
|
||||||
2i32,
|
|
||||||
(*private_key).binary,
|
|
||||||
(*private_key).bytes,
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
sqlite3_step(stmt);
|
|
||||||
sqlite3_finalize(stmt);
|
|
||||||
stmt = 0 as *mut sqlite3_stmt;
|
|
||||||
if 0 != set_default {
|
|
||||||
dc_sqlite3_execute(
|
|
||||||
context,
|
context,
|
||||||
&context.sql.clone().read().unwrap(),
|
&context.sql.clone().read().unwrap(),
|
||||||
b"UPDATE keypairs SET is_default=0;\x00" as *const u8 as *const libc::c_char,
|
b"DELETE FROM keypairs WHERE public_key=? OR private_key=?;\x00" as *const u8
|
||||||
|
as *const libc::c_char,
|
||||||
);
|
);
|
||||||
}
|
sqlite3_bind_blob(stmt, 1i32, (*public_key).binary, (*public_key).bytes, None);
|
||||||
self_addr = dc_sqlite3_get_config(
|
sqlite3_bind_blob(
|
||||||
context,
|
stmt,
|
||||||
&context.sql.clone().read().unwrap(),
|
2i32,
|
||||||
b"configured_addr\x00" as *const u8 as *const libc::c_char,
|
(*private_key).binary,
|
||||||
0 as *const libc::c_char,
|
(*private_key).bytes,
|
||||||
);
|
None,
|
||||||
if 0 == dc_key_save_self_keypair(
|
);
|
||||||
context,
|
sqlite3_step(stmt);
|
||||||
public_key,
|
sqlite3_finalize(stmt);
|
||||||
private_key,
|
stmt = 0 as *mut sqlite3_stmt;
|
||||||
self_addr,
|
if 0 != set_default {
|
||||||
set_default,
|
dc_sqlite3_execute(
|
||||||
&context.sql.clone().read().unwrap(),
|
context,
|
||||||
) {
|
&context.sql.clone().read().unwrap(),
|
||||||
|
b"UPDATE keypairs SET is_default=0;\x00" as *const u8 as *const libc::c_char,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
self_addr = dc_sqlite3_get_config(
|
||||||
|
context,
|
||||||
|
&context.sql.clone().read().unwrap(),
|
||||||
|
b"configured_addr\x00" as *const u8 as *const libc::c_char,
|
||||||
|
0 as *const libc::c_char,
|
||||||
|
);
|
||||||
|
if 0 == dc_key_save_self_keypair(
|
||||||
|
context,
|
||||||
|
public_key,
|
||||||
|
private_key,
|
||||||
|
self_addr,
|
||||||
|
set_default,
|
||||||
|
&context.sql.clone().read().unwrap(),
|
||||||
|
) {
|
||||||
|
dc_log_error(
|
||||||
|
context,
|
||||||
|
0i32,
|
||||||
|
b"Cannot save keypair.\x00" as *const u8 as *const libc::c_char,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
if !buf_preferencrypt.is_null() {
|
||||||
|
if strcmp(
|
||||||
|
buf_preferencrypt,
|
||||||
|
b"nopreference\x00" as *const u8 as *const libc::c_char,
|
||||||
|
) == 0i32
|
||||||
|
{
|
||||||
|
dc_sqlite3_set_config_int(
|
||||||
|
context,
|
||||||
|
&context.sql.clone().read().unwrap(),
|
||||||
|
b"e2ee_enabled\x00" as *const u8 as *const libc::c_char,
|
||||||
|
0i32,
|
||||||
|
);
|
||||||
|
} else if strcmp(
|
||||||
|
buf_preferencrypt,
|
||||||
|
b"mutual\x00" as *const u8 as *const libc::c_char,
|
||||||
|
) == 0i32
|
||||||
|
{
|
||||||
|
dc_sqlite3_set_config_int(
|
||||||
|
context,
|
||||||
|
&context.sql.clone().read().unwrap(),
|
||||||
|
b"e2ee_enabled\x00" as *const u8 as *const libc::c_char,
|
||||||
|
1i32,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
success = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
dc_log_error(
|
dc_log_error(
|
||||||
context,
|
context,
|
||||||
0i32,
|
0i32,
|
||||||
b"Cannot save keypair.\x00" as *const u8 as *const libc::c_char,
|
b"File does not contain a valid private key.\x00" as *const u8
|
||||||
|
as *const libc::c_char,
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
if !buf_preferencrypt.is_null() {
|
|
||||||
if strcmp(
|
|
||||||
buf_preferencrypt,
|
|
||||||
b"nopreference\x00" as *const u8 as *const libc::c_char,
|
|
||||||
) == 0i32
|
|
||||||
{
|
|
||||||
dc_sqlite3_set_config_int(
|
|
||||||
context,
|
|
||||||
&context.sql.clone().read().unwrap(),
|
|
||||||
b"e2ee_enabled\x00" as *const u8 as *const libc::c_char,
|
|
||||||
0i32,
|
|
||||||
);
|
|
||||||
} else if strcmp(
|
|
||||||
buf_preferencrypt,
|
|
||||||
b"mutual\x00" as *const u8 as *const libc::c_char,
|
|
||||||
) == 0i32
|
|
||||||
{
|
|
||||||
dc_sqlite3_set_config_int(
|
|
||||||
context,
|
|
||||||
&context.sql.clone().read().unwrap(),
|
|
||||||
b"e2ee_enabled\x00" as *const u8 as *const libc::c_char,
|
|
||||||
1i32,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
success = 1i32
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlite3_finalize(stmt);
|
sqlite3_finalize(stmt);
|
||||||
free(buf as *mut libc::c_void);
|
free(buf as *mut libc::c_void);
|
||||||
free(self_addr as *mut libc::c_void);
|
free(self_addr as *mut libc::c_void);
|
||||||
dc_key_unref(private_key);
|
|
||||||
dc_key_unref(public_key);
|
|
||||||
|
|
||||||
success
|
success
|
||||||
}
|
}
|
||||||
@@ -1579,8 +1573,6 @@ unsafe fn export_self_keys(context: &dc_context_t, dir: *const libc::c_char) ->
|
|||||||
let mut export_errors: libc::c_int = 0i32;
|
let mut export_errors: libc::c_int = 0i32;
|
||||||
let mut id: libc::c_int;
|
let mut id: libc::c_int;
|
||||||
let mut is_default: libc::c_int;
|
let mut is_default: libc::c_int;
|
||||||
let public_key: *mut dc_key_t = dc_key_new();
|
|
||||||
let private_key: *mut dc_key_t = dc_key_new();
|
|
||||||
let stmt = dc_sqlite3_prepare(
|
let stmt = dc_sqlite3_prepare(
|
||||||
context,
|
context,
|
||||||
&context.sql.clone().read().unwrap(),
|
&context.sql.clone().read().unwrap(),
|
||||||
@@ -1590,13 +1582,14 @@ unsafe fn export_self_keys(context: &dc_context_t, dir: *const libc::c_char) ->
|
|||||||
if !stmt.is_null() {
|
if !stmt.is_null() {
|
||||||
while sqlite3_step(stmt) == 100i32 {
|
while sqlite3_step(stmt) == 100i32 {
|
||||||
id = sqlite3_column_int(stmt, 0i32);
|
id = sqlite3_column_int(stmt, 0i32);
|
||||||
dc_key_set_from_stmt(public_key, stmt, 1i32, 0i32);
|
let public_key = Key::from_stmt(stmt, 1i32, KeyType::Public);
|
||||||
dc_key_set_from_stmt(private_key, stmt, 2i32, 1i32);
|
let private_key = Key::from_stmt(stmt, 2i32, KeyType::Private);
|
||||||
|
|
||||||
is_default = sqlite3_column_int(stmt, 3i32);
|
is_default = sqlite3_column_int(stmt, 3i32);
|
||||||
if 0 == export_key_to_asc_file(context, dir, id, public_key, is_default) {
|
if 0 == export_key_to_asc_file(context, dir, id, &public_key, is_default) {
|
||||||
export_errors += 1
|
export_errors += 1
|
||||||
}
|
}
|
||||||
if 0 == export_key_to_asc_file(context, dir, id, private_key, is_default) {
|
if 0 == export_key_to_asc_file(context, dir, id, &private_key, is_default) {
|
||||||
export_errors += 1
|
export_errors += 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1605,8 +1598,6 @@ unsafe fn export_self_keys(context: &dc_context_t, dir: *const libc::c_char) ->
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
sqlite3_finalize(stmt);
|
sqlite3_finalize(stmt);
|
||||||
dc_key_unref(public_key);
|
|
||||||
dc_key_unref(private_key);
|
|
||||||
|
|
||||||
success
|
success
|
||||||
}
|
}
|
||||||
@@ -1619,7 +1610,7 @@ unsafe fn export_key_to_asc_file(
|
|||||||
context: &dc_context_t,
|
context: &dc_context_t,
|
||||||
dir: *const libc::c_char,
|
dir: *const libc::c_char,
|
||||||
id: libc::c_int,
|
id: libc::c_int,
|
||||||
key: *const dc_key_t,
|
key: &Key,
|
||||||
is_default: libc::c_int,
|
is_default: libc::c_int,
|
||||||
) -> libc::c_int {
|
) -> libc::c_int {
|
||||||
let mut success: libc::c_int = 0i32;
|
let mut success: libc::c_int = 0i32;
|
||||||
@@ -1653,7 +1644,7 @@ unsafe fn export_key_to_asc_file(
|
|||||||
file_name,
|
file_name,
|
||||||
);
|
);
|
||||||
dc_delete_file(context, file_name);
|
dc_delete_file(context, file_name);
|
||||||
if 0 == dc_key_render_asc_to_file(key, file_name, context) {
|
if !key.write_asc_to_file(file_name, context) {
|
||||||
dc_log_error(
|
dc_log_error(
|
||||||
context,
|
context,
|
||||||
0i32,
|
0i32,
|
||||||
|
|||||||
706
src/dc_key.rs
706
src/dc_key.rs
@@ -1,16 +1,16 @@
|
|||||||
use mmime::mailmime_content::*;
|
|
||||||
use mmime::mmapstring::*;
|
|
||||||
use mmime::other::*;
|
|
||||||
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::ffi::CString;
|
use std::ffi::{CStr, CString};
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
|
|
||||||
use libc;
|
use libc;
|
||||||
|
use mmime::mailmime_content::*;
|
||||||
|
use mmime::mmapstring::*;
|
||||||
|
use mmime::other::*;
|
||||||
use pgp::composed::{Deserializable, SignedPublicKey, SignedSecretKey};
|
use pgp::composed::{Deserializable, SignedPublicKey, SignedSecretKey};
|
||||||
use pgp::ser::Serialize;
|
use pgp::ser::Serialize;
|
||||||
|
|
||||||
|
use crate::constants::*;
|
||||||
use crate::dc_context::dc_context_t;
|
use crate::dc_context::dc_context_t;
|
||||||
use crate::dc_log::*;
|
use crate::dc_log::*;
|
||||||
use crate::dc_pgp::*;
|
use crate::dc_pgp::*;
|
||||||
@@ -20,480 +20,296 @@ use crate::dc_tools::*;
|
|||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
use crate::x::*;
|
use crate::x::*;
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||||
#[repr(C)]
|
pub enum Key {
|
||||||
pub struct dc_key_t {
|
Public(SignedPublicKey),
|
||||||
pub binary: *mut libc::c_void,
|
Secret(SignedSecretKey),
|
||||||
pub bytes: libc::c_int,
|
|
||||||
pub type_0: libc::c_int,
|
|
||||||
pub _m_heap_refcnt: libc::c_int,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
impl Key {
|
||||||
pub unsafe fn toupper(mut _c: libc::c_int) -> libc::c_int {
|
pub fn is_public(&self) -> bool {
|
||||||
return __toupper(_c);
|
match self {
|
||||||
}
|
Key::Public(_) => true,
|
||||||
|
Key::Secret(_) => false,
|
||||||
pub unsafe fn dc_key_new() -> *mut dc_key_t {
|
|
||||||
let mut key: *mut dc_key_t;
|
|
||||||
key = calloc(1, ::std::mem::size_of::<dc_key_t>()) as *mut dc_key_t;
|
|
||||||
if key.is_null() {
|
|
||||||
exit(44i32);
|
|
||||||
}
|
|
||||||
(*key)._m_heap_refcnt = 1i32;
|
|
||||||
|
|
||||||
key
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn dc_key_ref(mut key: *mut dc_key_t) -> *mut dc_key_t {
|
|
||||||
if key.is_null() {
|
|
||||||
return 0 as *mut dc_key_t;
|
|
||||||
}
|
|
||||||
(*key)._m_heap_refcnt += 1;
|
|
||||||
|
|
||||||
key
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn dc_key_unref(mut key: *mut dc_key_t) {
|
|
||||||
if key.is_null() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
(*key)._m_heap_refcnt -= 1;
|
|
||||||
if (*key)._m_heap_refcnt != 0i32 {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
dc_key_empty(key);
|
|
||||||
free(key as *mut libc::c_void);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn dc_key_empty(mut key: *mut dc_key_t) {
|
|
||||||
if key.is_null() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (*key).type_0 == 1i32 {
|
|
||||||
dc_wipe_secret_mem((*key).binary, (*key).bytes as size_t);
|
|
||||||
}
|
|
||||||
free((*key).binary);
|
|
||||||
(*key).binary = 0 as *mut libc::c_void;
|
|
||||||
(*key).bytes = 0i32;
|
|
||||||
(*key).type_0 = 0i32;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn dc_wipe_secret_mem(buf: *mut libc::c_void, buf_bytes: size_t) {
|
|
||||||
if buf.is_null() || buf_bytes <= 0 {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
memset(buf, 0i32, buf_bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO should return bool /rtn
|
|
||||||
pub unsafe fn dc_key_set_from_binary(
|
|
||||||
mut key: *mut dc_key_t,
|
|
||||||
data: *const libc::c_void,
|
|
||||||
bytes: libc::c_int,
|
|
||||||
type_0: libc::c_int,
|
|
||||||
) -> libc::c_int {
|
|
||||||
dc_key_empty(key);
|
|
||||||
if key.is_null() || data == 0 as *mut libc::c_void || bytes <= 0i32 {
|
|
||||||
return 0i32;
|
|
||||||
}
|
|
||||||
(*key).binary = malloc(bytes as size_t);
|
|
||||||
if (*key).binary.is_null() {
|
|
||||||
exit(40i32);
|
|
||||||
}
|
|
||||||
memcpy((*key).binary, data, bytes as size_t);
|
|
||||||
(*key).bytes = bytes;
|
|
||||||
(*key).type_0 = type_0;
|
|
||||||
|
|
||||||
1
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn dc_key_set_from_key(key: *mut dc_key_t, o: *const dc_key_t) -> libc::c_int {
|
|
||||||
dc_key_empty(key);
|
|
||||||
if key.is_null() || o.is_null() {
|
|
||||||
return 0i32;
|
|
||||||
}
|
|
||||||
|
|
||||||
dc_key_set_from_binary(key, (*o).binary, (*o).bytes, (*o).type_0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO should return bool /rtn
|
|
||||||
pub unsafe fn dc_key_set_from_stmt(
|
|
||||||
key: *mut dc_key_t,
|
|
||||||
stmt: *mut sqlite3_stmt,
|
|
||||||
index: libc::c_int,
|
|
||||||
type_0: libc::c_int,
|
|
||||||
) -> libc::c_int {
|
|
||||||
dc_key_empty(key);
|
|
||||||
if key.is_null() || stmt.is_null() {
|
|
||||||
return 0i32;
|
|
||||||
}
|
|
||||||
|
|
||||||
dc_key_set_from_binary(
|
|
||||||
key,
|
|
||||||
sqlite3_column_blob(stmt, index) as *mut libc::c_uchar as *const libc::c_void,
|
|
||||||
sqlite3_column_bytes(stmt, index),
|
|
||||||
type_0,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO should return bool /rtn
|
|
||||||
pub unsafe fn dc_key_set_from_base64(
|
|
||||||
key: *mut dc_key_t,
|
|
||||||
base64: *const libc::c_char,
|
|
||||||
type_0: libc::c_int,
|
|
||||||
) -> libc::c_int {
|
|
||||||
let mut indx: size_t = 0i32 as size_t;
|
|
||||||
let mut result_len: size_t = 0i32 as size_t;
|
|
||||||
let mut result: *mut libc::c_char = 0 as *mut libc::c_char;
|
|
||||||
dc_key_empty(key);
|
|
||||||
if key.is_null() || base64.is_null() {
|
|
||||||
return 0i32;
|
|
||||||
}
|
|
||||||
if mailmime_base64_body_parse(
|
|
||||||
base64,
|
|
||||||
strlen(base64),
|
|
||||||
&mut indx,
|
|
||||||
&mut result,
|
|
||||||
&mut result_len,
|
|
||||||
) != MAILIMF_NO_ERROR as libc::c_int
|
|
||||||
|| result.is_null()
|
|
||||||
|| result_len == 0
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
dc_key_set_from_binary(
|
|
||||||
key,
|
|
||||||
result as *const libc::c_void,
|
|
||||||
result_len as libc::c_int,
|
|
||||||
type_0,
|
|
||||||
);
|
|
||||||
mmap_string_unref(result);
|
|
||||||
|
|
||||||
1
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO should return bool /rtn
|
|
||||||
pub unsafe fn dc_key_equals(key: *const dc_key_t, o: *const dc_key_t) -> libc::c_int {
|
|
||||||
if key.is_null()
|
|
||||||
|| o.is_null()
|
|
||||||
|| (*key).binary.is_null()
|
|
||||||
|| (*key).bytes <= 0i32
|
|
||||||
|| (*o).binary.is_null()
|
|
||||||
|| (*o).bytes <= 0i32
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (*key).bytes != (*o).bytes {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (*key).type_0 != (*o).type_0 {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if memcmp((*key).binary, (*o).binary, (*o).bytes as size_t) == 0 {
|
|
||||||
1
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO should return bool /rtn
|
|
||||||
pub unsafe fn dc_key_save_self_keypair(
|
|
||||||
context: &dc_context_t,
|
|
||||||
public_key: *const dc_key_t,
|
|
||||||
private_key: *const dc_key_t,
|
|
||||||
addr: *const libc::c_char,
|
|
||||||
is_default: libc::c_int,
|
|
||||||
sql: &dc_sqlite3_t,
|
|
||||||
) -> libc::c_int {
|
|
||||||
let mut success: libc::c_int = 0i32;
|
|
||||||
let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt;
|
|
||||||
if !(public_key.is_null()
|
|
||||||
|| private_key.is_null()
|
|
||||||
|| addr.is_null()
|
|
||||||
|| (*public_key).binary.is_null()
|
|
||||||
|| (*private_key).binary.is_null())
|
|
||||||
{
|
|
||||||
stmt =
|
|
||||||
dc_sqlite3_prepare(
|
|
||||||
context,
|
|
||||||
sql,
|
|
||||||
b"INSERT INTO keypairs (addr, is_default, public_key, private_key, created) VALUES (?,?,?,?,?);\x00"
|
|
||||||
as *const u8 as *const libc::c_char);
|
|
||||||
sqlite3_bind_text(stmt, 1i32, addr, -1i32, None);
|
|
||||||
sqlite3_bind_int(stmt, 2i32, is_default);
|
|
||||||
sqlite3_bind_blob(stmt, 3i32, (*public_key).binary, (*public_key).bytes, None);
|
|
||||||
sqlite3_bind_blob(
|
|
||||||
stmt,
|
|
||||||
4i32,
|
|
||||||
(*private_key).binary,
|
|
||||||
(*private_key).bytes,
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
sqlite3_bind_int64(stmt, 5i32, time(0 as *mut time_t) as sqlite3_int64);
|
|
||||||
if !(sqlite3_step(stmt) != 101i32) {
|
|
||||||
success = 1i32
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sqlite3_finalize(stmt);
|
|
||||||
|
|
||||||
success
|
pub fn is_secret(&self) -> bool {
|
||||||
}
|
!self.is_public()
|
||||||
|
}
|
||||||
|
|
||||||
// TODO should return bool /rtn
|
pub fn from_slice(bytes: &[u8], key_type: KeyType) -> Option<Self> {
|
||||||
pub unsafe fn dc_key_load_self_public(
|
match key_type {
|
||||||
context: &dc_context_t,
|
KeyType::Public => SignedPublicKey::from_bytes(Cursor::new(bytes))
|
||||||
key: *mut dc_key_t,
|
.map(|k| Key::Public(k))
|
||||||
self_addr: *const libc::c_char,
|
.ok(),
|
||||||
sql: &dc_sqlite3_t,
|
KeyType::Secret => SignedSecretKey::from_bytes(Cursor::new(bytes))
|
||||||
) -> libc::c_int {
|
.map(|k| Key::Secret(k))
|
||||||
let mut success: libc::c_int = 0i32;
|
.ok(),
|
||||||
let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt;
|
}
|
||||||
if !(key.is_null() || self_addr.is_null()) {
|
}
|
||||||
dc_key_empty(key);
|
|
||||||
stmt = dc_sqlite3_prepare(
|
pub fn from_binary(
|
||||||
|
data: *const libc::c_void,
|
||||||
|
len: libc::c_int,
|
||||||
|
key_type: KeyType,
|
||||||
|
) -> Option<Self> {
|
||||||
|
assert!(!data.is_null(), "missing data");
|
||||||
|
assert!(len > 0);
|
||||||
|
|
||||||
|
let bytes = unsafe { slice::from_raw_parts(data, len) };
|
||||||
|
Self::from_slice(bytes, key_type)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_stmt(
|
||||||
|
stmt: *mut sqlite3_stmt,
|
||||||
|
index: libc::c_int,
|
||||||
|
key_type: KeyType,
|
||||||
|
) -> Option<Self> {
|
||||||
|
assert!(!stmt.is_null(), "missing statement");
|
||||||
|
|
||||||
|
let data = unsafe {
|
||||||
|
sqlite3_column_blob(stmt, index) as *mut libc::c_uchar as *const libc::c_void
|
||||||
|
};
|
||||||
|
let len = unsafe { sqlite3_column_bytes(stmt, index) };
|
||||||
|
|
||||||
|
Self::from_binary(data, len, key_type)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_base64(encoded_data: &str, key_type: KeyType) -> Option<Self> {
|
||||||
|
// TODO: strip newlines and other whitespace
|
||||||
|
let bytes = encoded_data.as_bytes();
|
||||||
|
|
||||||
|
base64::decode(bytes)
|
||||||
|
.ok()
|
||||||
|
.and_then(|decoded| Self::from_slice(&decoded, key_type))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_self_public(
|
||||||
|
context: &dc_context_t,
|
||||||
|
self_addr: *const libc::c_char,
|
||||||
|
sql: &dc_sqlite3_t,
|
||||||
|
) -> Option<Self> {
|
||||||
|
if self_addr.is_null() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let stmt = dc_sqlite3_prepare(
|
||||||
context,
|
context,
|
||||||
sql,
|
sql,
|
||||||
b"SELECT public_key FROM keypairs WHERE addr=? AND is_default=1;\x00" as *const u8
|
b"SELECT public_key FROM keypairs WHERE addr=? AND is_default=1;\x00" as *const u8
|
||||||
as *const libc::c_char,
|
as *const libc::c_char,
|
||||||
);
|
);
|
||||||
sqlite3_bind_text(stmt, 1i32, self_addr, -1i32, None);
|
sqlite3_bind_text(stmt, 1, self_addr, -1, None);
|
||||||
if !(sqlite3_step(stmt) != 100i32) {
|
|
||||||
dc_key_set_from_stmt(key, stmt, 0i32, 0i32);
|
let key = if sqlite3_step(stmt) == 100 {
|
||||||
success = 1i32
|
Self::from_stmt(stmt, 0, KeyType::Public);
|
||||||
}
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
sqlite3_finalize(stmt);
|
||||||
|
|
||||||
|
key
|
||||||
}
|
}
|
||||||
sqlite3_finalize(stmt);
|
|
||||||
|
|
||||||
success
|
pub fn from_self_private(
|
||||||
}
|
context: &dc_context_t,
|
||||||
|
self_addr: *const libc::c_char,
|
||||||
|
sql: &dc_sqlite3_t,
|
||||||
|
) -> Option<Self> {
|
||||||
|
if self_addr.is_null() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO should return bool /rtn
|
let stmt = dc_sqlite3_prepare(
|
||||||
pub unsafe fn dc_key_load_self_private(
|
|
||||||
context: &dc_context_t,
|
|
||||||
key: *mut dc_key_t,
|
|
||||||
self_addr: *const libc::c_char,
|
|
||||||
sql: &dc_sqlite3_t,
|
|
||||||
) -> libc::c_int {
|
|
||||||
let mut success: libc::c_int = 0i32;
|
|
||||||
let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt;
|
|
||||||
if !(key.is_null() || self_addr.is_null()) {
|
|
||||||
dc_key_empty(key);
|
|
||||||
stmt = dc_sqlite3_prepare(
|
|
||||||
context,
|
context,
|
||||||
sql,
|
sql,
|
||||||
b"SELECT private_key FROM keypairs WHERE addr=? AND is_default=1;\x00" as *const u8
|
b"SELECT private_key FROM keypairs WHERE addr=? AND is_default=1;\x00" as *const u8
|
||||||
as *const libc::c_char,
|
as *const libc::c_char,
|
||||||
);
|
);
|
||||||
sqlite3_bind_text(stmt, 1i32, self_addr, -1i32, None);
|
sqlite3_bind_text(stmt, 1, self_addr, -1, None);
|
||||||
if !(sqlite3_step(stmt) != 100i32) {
|
|
||||||
dc_key_set_from_stmt(key, stmt, 0i32, 1i32);
|
let key = if sqlite3_step(stmt) == 100 {
|
||||||
success = 1i32;
|
Self::from_stmt(stmt, 0, KeyType::Secret)
|
||||||
}
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
sqlite3_finalize(stmt);
|
||||||
|
|
||||||
|
key
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn to_base64(&self, break_every: usize) -> String {
|
||||||
|
let buf = self.0.to_bytes().expect("failed to serialize key");
|
||||||
|
|
||||||
|
let encoded = base64::encode(&buf);
|
||||||
|
encoded
|
||||||
|
.as_bytes()
|
||||||
|
.chunks(break_every)
|
||||||
|
.fold(String::new(), |mut res, buf| {
|
||||||
|
// safe because we are using a base64 encoded string
|
||||||
|
res += unsafe { std::str::from_utf8_unchecked(buf) };
|
||||||
|
res += " ";
|
||||||
|
res
|
||||||
|
})
|
||||||
|
.trim()
|
||||||
|
.to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// the result must be freed
|
||||||
|
pub fn to_base64_c(&self, break_every: usize) -> *mut libc::c_char {
|
||||||
|
let res = self.to_base64(break_every);
|
||||||
|
let res_c = CString::new(res.trim()).unwrap();
|
||||||
|
|
||||||
|
// need to use strdup to allocate the result with malloc
|
||||||
|
// so it can be `free`d later.
|
||||||
|
unsafe { libc::strdup(res_c.as_ptr()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Each header line must be terminated by `\r\n`, the result must be freed.
|
||||||
|
pub fn to_asc_c(&self, header: Option<(&str, &str)>) -> *mut libc::c_char {
|
||||||
|
let headers = header.map(|(key, value)| {
|
||||||
|
let mut m = BTreeMap::new();
|
||||||
|
m.insert(key.to_string(), value.to_string());
|
||||||
|
m
|
||||||
|
});
|
||||||
|
|
||||||
|
let buf = self
|
||||||
|
.0
|
||||||
|
.to_armored_string(headers.as_ref())
|
||||||
|
.expect("failed to serialize key");
|
||||||
|
let buf_c = CString::new(buf).unwrap();
|
||||||
|
|
||||||
|
// need to use strdup to allocate the result with malloc
|
||||||
|
// so it can be `free`d later.
|
||||||
|
unsafe { libc::strdup(buf_c.as_ptr()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_asc_to_file(&self, file: *const libc::c_char, context: &dc_context_t) -> bool {
|
||||||
|
if file.is_null() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let file_content = self.to_asc(None);
|
||||||
|
|
||||||
|
let success = if 0
|
||||||
|
== unsafe {
|
||||||
|
dc_write_file(
|
||||||
|
context,
|
||||||
|
file,
|
||||||
|
file_content as *const libc::c_void,
|
||||||
|
strlen(file_content),
|
||||||
|
)
|
||||||
|
} {
|
||||||
|
error!(context, 0, "Cannot write key to %s", file);
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
};
|
||||||
|
|
||||||
|
free(file_content as *mut libc::c_void);
|
||||||
|
|
||||||
|
success
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fingerprint(&self) -> String {
|
||||||
|
hex::encode_upper(self.0.fingerprint())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fingerprint_c(&self) -> *mut libc::c_char {
|
||||||
|
let res = CString::new(self.fingerprint()).unwrap();
|
||||||
|
|
||||||
|
unsafe { libc::strdup(res.as_ptr()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn formatted_fingerprint(&self) -> String {
|
||||||
|
let rawhex = self.fingerprint();
|
||||||
|
dc_format_fingerprint(&rawhex)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn formatted_fingerprint_c(&self) -> String {
|
||||||
|
let res = CString::new(self.formatted_fingerprint()).unwrap();
|
||||||
|
|
||||||
|
unsafe { libc::strdup(res.as_ptr()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dc_key_save_self_keypair(
|
||||||
|
context: &dc_context_t,
|
||||||
|
public_key: &Key,
|
||||||
|
private_key: &Key,
|
||||||
|
addr: *const libc::c_char,
|
||||||
|
is_default: libc::c_int,
|
||||||
|
sql: &dc_sqlite3_t,
|
||||||
|
) -> bool {
|
||||||
|
if addr.is_null() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
let stmt = dc_sqlite3_prepare(
|
||||||
|
context,
|
||||||
|
sql,
|
||||||
|
b"INSERT INTO keypairs (addr, is_default, public_key, private_key, created) VALUES (?,?,?,?,?);\x00"
|
||||||
|
as *const u8 as *const libc::c_char
|
||||||
|
);
|
||||||
|
|
||||||
|
sqlite3_bind_text(stmt, 1, addr, -1, None);
|
||||||
|
sqlite3_bind_int(stmt, 2, is_default);
|
||||||
|
let pub_bytes = public_key.to_bytes();
|
||||||
|
let sec_bytes = private_key.to_bytes();
|
||||||
|
sqlite3_bind_blob(stmt, 3, pub_bytes.as_ptr(), pub_bytes.len(), None);
|
||||||
|
sqlite3_bind_blob(stmt, 4, sec_bytes.as_ptr(), sec_bytes.len(), None);
|
||||||
|
sqlite3_bind_int64(stmt, 5, time(0 as *mut time_t) as sqlite3_int64);
|
||||||
|
let success = if sqlite3_step(stmt) == 101 {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
sqlite3_finalize(stmt);
|
sqlite3_finalize(stmt);
|
||||||
|
|
||||||
success
|
success
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dc_key_render_base64_string(key: *const dc_key_t, break_every: usize) -> String {
|
/// Make a fingerprint human-readable, in hex format.
|
||||||
assert!(!key.is_null(), "missing key");
|
pub fn dc_format_fingerprint(fingerprint: &str) -> String {
|
||||||
|
// split key into chunks of 4 with space, and 20 newline
|
||||||
let key = unsafe { *key };
|
fingerprint
|
||||||
let bytes = unsafe { slice::from_raw_parts(key.binary as *const u8, key.bytes as usize) };
|
|
||||||
assert_eq!(bytes.len(), key.bytes as usize);
|
|
||||||
|
|
||||||
let buf = if key.type_0 == 0 {
|
|
||||||
// public key
|
|
||||||
let skey = SignedPublicKey::from_bytes(Cursor::new(bytes)).expect("invalid pub key");
|
|
||||||
skey.to_bytes().expect("failed to serialize key")
|
|
||||||
} else {
|
|
||||||
// secret key
|
|
||||||
let skey = SignedSecretKey::from_bytes(Cursor::new(bytes)).expect("invalid sec key");
|
|
||||||
skey.to_bytes().expect("failed to serialize key")
|
|
||||||
};
|
|
||||||
|
|
||||||
let encoded = base64::encode(&buf);
|
|
||||||
encoded
|
|
||||||
.as_bytes()
|
.as_bytes()
|
||||||
.chunks(break_every)
|
.chunks(4)
|
||||||
.fold(String::new(), |mut res, buf| {
|
.chunks(5)
|
||||||
// safe because we are using a base64 encoded string
|
.map(|chunk| chunk.join(" "))
|
||||||
res += unsafe { std::str::from_utf8_unchecked(buf) };
|
.join("\n")
|
||||||
res += " ";
|
|
||||||
res
|
|
||||||
})
|
|
||||||
.trim()
|
|
||||||
.to_string()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the result must be freed */
|
/// Bring a human-readable or otherwise formatted fingerprint back to the 40-characters-uppercase-hex format.
|
||||||
pub fn dc_key_render_base64(key: *const dc_key_t, break_every: usize) -> *mut libc::c_char {
|
pub unsafe fn dc_normalize_fingerprint(fp: &str) -> String {
|
||||||
let res = dc_key_render_base64_string(key, break_every);
|
fp.to_uppercase()
|
||||||
let res_c = CString::new(res.trim()).unwrap();
|
.chars()
|
||||||
|
.filter(|c| c >= '0' && c <= '9' || c >= 'A' && c <= 'F')
|
||||||
// need to use strdup to allocate the result with malloc
|
.join("")
|
||||||
// so it can be `free`d later.
|
|
||||||
unsafe { libc::strdup(res_c.as_ptr()) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// each header line must be terminated by `\r\n`, the result must be freed.
|
#[cfg(test)]
|
||||||
pub fn dc_key_render_asc(key: *const dc_key_t, header: Option<(&str, &str)>) -> *mut libc::c_char {
|
mod tests {
|
||||||
if key.is_null() {
|
use super::*;
|
||||||
return std::ptr::null_mut();
|
|
||||||
|
#[test]
|
||||||
|
fn test_normalize_fingerprint() {
|
||||||
|
let fingerprint = dc_normalize_fingerprint(" 1234 567890 \n AbcD abcdef ABCDEF ");
|
||||||
|
|
||||||
|
assert_eq!(fingerprint, "1234567890ABCDABCDEFABCDEF");
|
||||||
}
|
}
|
||||||
|
|
||||||
let key = unsafe { *key };
|
#[test]
|
||||||
|
fn test_format_fingerprint() {
|
||||||
|
let fingerprint = dc_normalize_fingerprint("1234567890ABCDABCDEFABCDEF1234567890ABCD");
|
||||||
|
|
||||||
let headers = header.map(|(key, value)| {
|
assert_eq!(
|
||||||
let mut m = BTreeMap::new();
|
fingerprint,
|
||||||
m.insert(key.to_string(), value.to_string());
|
"1234 5678 90AB CDAB CDEF\nABCD EF12 3456 7890 ABCD"
|
||||||
m
|
|
||||||
});
|
|
||||||
|
|
||||||
let bytes = unsafe { slice::from_raw_parts(key.binary as *const u8, key.bytes as usize) };
|
|
||||||
|
|
||||||
let buf = if key.type_0 == 0 {
|
|
||||||
// public key
|
|
||||||
let skey = SignedPublicKey::from_bytes(Cursor::new(bytes)).expect("invalid key");
|
|
||||||
skey.to_armored_string(headers.as_ref())
|
|
||||||
.expect("failed to serialize key")
|
|
||||||
} else {
|
|
||||||
// secret key
|
|
||||||
let skey = SignedSecretKey::from_bytes(Cursor::new(bytes)).expect("invalid key");
|
|
||||||
skey.to_armored_string(headers.as_ref())
|
|
||||||
.expect("failed to serialize key")
|
|
||||||
};
|
|
||||||
|
|
||||||
let buf_c = CString::new(buf).unwrap();
|
|
||||||
|
|
||||||
// need to use strdup to allocate the result with malloc
|
|
||||||
// so it can be `free`d later.
|
|
||||||
unsafe { libc::strdup(buf_c.as_ptr()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn dc_key_render_asc_to_file(
|
|
||||||
key: *const dc_key_t,
|
|
||||||
file: *const libc::c_char,
|
|
||||||
context: &dc_context_t,
|
|
||||||
) -> libc::c_int {
|
|
||||||
let mut success: libc::c_int = 0i32;
|
|
||||||
let mut file_content: *mut libc::c_char = 0 as *mut libc::c_char;
|
|
||||||
|
|
||||||
if !(key.is_null() || file.is_null()) {
|
|
||||||
file_content = dc_key_render_asc(key, None);
|
|
||||||
|
|
||||||
if !file_content.is_null() {
|
|
||||||
if 0 == dc_write_file(
|
|
||||||
context,
|
|
||||||
file,
|
|
||||||
file_content as *const libc::c_void,
|
|
||||||
strlen(file_content),
|
|
||||||
) {
|
|
||||||
dc_log_error(
|
|
||||||
context,
|
|
||||||
0i32,
|
|
||||||
b"Cannot write key to %s\x00" as *const u8 as *const libc::c_char,
|
|
||||||
file,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
success = 1i32
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(file_content as *mut libc::c_void);
|
|
||||||
|
|
||||||
success
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn dc_format_fingerprint(fingerprint: *const libc::c_char) -> *mut libc::c_char {
|
|
||||||
let mut i: libc::c_int = 0i32;
|
|
||||||
let fingerprint_len: libc::c_int = strlen(fingerprint) as libc::c_int;
|
|
||||||
let mut ret: dc_strbuilder_t = dc_strbuilder_t {
|
|
||||||
buf: 0 as *mut libc::c_char,
|
|
||||||
allocated: 0,
|
|
||||||
free: 0,
|
|
||||||
eos: 0 as *mut libc::c_char,
|
|
||||||
};
|
|
||||||
dc_strbuilder_init(&mut ret, 0i32);
|
|
||||||
while 0 != *fingerprint.offset(i as isize) {
|
|
||||||
dc_strbuilder_catf(
|
|
||||||
&mut ret as *mut dc_strbuilder_t,
|
|
||||||
b"%c\x00" as *const u8 as *const libc::c_char,
|
|
||||||
*fingerprint.offset(i as isize) as libc::c_int,
|
|
||||||
);
|
);
|
||||||
i += 1;
|
|
||||||
if i != fingerprint_len {
|
|
||||||
if i % 20i32 == 0i32 {
|
|
||||||
dc_strbuilder_cat(&mut ret, b"\n\x00" as *const u8 as *const libc::c_char);
|
|
||||||
} else if i % 4i32 == 0i32 {
|
|
||||||
dc_strbuilder_cat(&mut ret, b" \x00" as *const u8 as *const libc::c_char);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret.buf
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn dc_normalize_fingerprint(in_0: *const libc::c_char) -> *mut libc::c_char {
|
|
||||||
if in_0.is_null() {
|
|
||||||
return 0 as *mut libc::c_char;
|
|
||||||
}
|
|
||||||
let mut out: dc_strbuilder_t = dc_strbuilder_t {
|
|
||||||
buf: 0 as *mut libc::c_char,
|
|
||||||
allocated: 0,
|
|
||||||
free: 0,
|
|
||||||
eos: 0 as *mut libc::c_char,
|
|
||||||
};
|
|
||||||
dc_strbuilder_init(&mut out, 0i32);
|
|
||||||
let mut p1: *const libc::c_char = in_0;
|
|
||||||
while 0 != *p1 {
|
|
||||||
if *p1 as libc::c_int >= '0' as i32 && *p1 as libc::c_int <= '9' as i32
|
|
||||||
|| *p1 as libc::c_int >= 'A' as i32 && *p1 as libc::c_int <= 'F' as i32
|
|
||||||
|| *p1 as libc::c_int >= 'a' as i32 && *p1 as libc::c_int <= 'f' as i32
|
|
||||||
{
|
|
||||||
dc_strbuilder_catf(
|
|
||||||
&mut out as *mut dc_strbuilder_t,
|
|
||||||
b"%c\x00" as *const u8 as *const libc::c_char,
|
|
||||||
toupper(*p1 as libc::c_int),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
p1 = p1.offset(1isize)
|
|
||||||
}
|
|
||||||
|
|
||||||
out.buf
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn dc_key_get_fingerprint(
|
|
||||||
context: &dc_context_t,
|
|
||||||
key: *const dc_key_t,
|
|
||||||
) -> *mut libc::c_char {
|
|
||||||
let mut fingerprint_buf: *mut uint8_t = 0 as *mut uint8_t;
|
|
||||||
let mut fingerprint_bytes: size_t = 0i32 as size_t;
|
|
||||||
let mut fingerprint_hex: *mut libc::c_char = 0 as *mut libc::c_char;
|
|
||||||
if !key.is_null() {
|
|
||||||
if !(0
|
|
||||||
== dc_pgp_calc_fingerprint(context, key, &mut fingerprint_buf, &mut fingerprint_bytes))
|
|
||||||
{
|
|
||||||
fingerprint_hex = dc_binary_to_uc_hex(fingerprint_buf, fingerprint_bytes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(fingerprint_buf as *mut libc::c_void);
|
|
||||||
return if !fingerprint_hex.is_null() {
|
|
||||||
fingerprint_hex
|
|
||||||
} else {
|
|
||||||
dc_strdup(0 as *const libc::c_char)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub unsafe fn dc_key_get_formatted_fingerprint(
|
|
||||||
context: &dc_context_t,
|
|
||||||
key: *const dc_key_t,
|
|
||||||
) -> *mut libc::c_char {
|
|
||||||
let rawhex: *mut libc::c_char = dc_key_get_fingerprint(context, key);
|
|
||||||
let formatted: *mut libc::c_char = dc_format_fingerprint(rawhex);
|
|
||||||
free(rawhex as *mut libc::c_void);
|
|
||||||
|
|
||||||
formatted
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,86 +2,41 @@ use crate::dc_context::dc_context_t;
|
|||||||
use crate::dc_key::*;
|
use crate::dc_key::*;
|
||||||
use crate::dc_sqlite3::*;
|
use crate::dc_sqlite3::*;
|
||||||
use crate::types::*;
|
use crate::types::*;
|
||||||
use crate::x::*;
|
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Default, Clone, Debug)]
|
||||||
#[repr(C)]
|
|
||||||
pub struct dc_keyring_t {
|
pub struct dc_keyring_t {
|
||||||
pub keys: *mut *mut dc_key_t,
|
keys: Vec<Key>,
|
||||||
pub count: libc::c_int,
|
|
||||||
pub allocated: libc::c_int,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn dc_keyring_new() -> *mut dc_keyring_t {
|
impl dc_keyring_t {
|
||||||
let keyring: *mut dc_keyring_t;
|
pub fn add(&mut self, key: Key) {
|
||||||
keyring = calloc(1, ::std::mem::size_of::<dc_keyring_t>()) as *mut dc_keyring_t;
|
self.keys.push(key);
|
||||||
if keyring.is_null() {
|
|
||||||
exit(42i32);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
keyring
|
pub fn load_self_private_for_decrypting(
|
||||||
}
|
&mut self,
|
||||||
|
context: &dc_context_t,
|
||||||
pub unsafe fn dc_keyring_unref(keyring: *mut dc_keyring_t) {
|
self_addr: *const libc::c_char,
|
||||||
if keyring.is_null() {
|
sql: &dc_sqlite3_t,
|
||||||
return;
|
) -> bool {
|
||||||
}
|
// Can we prevent keyring and self_addr to be null?
|
||||||
let mut i: libc::c_int = 0i32;
|
if self_addr.is_null() {
|
||||||
while i < (*keyring).count {
|
return false;
|
||||||
dc_key_unref(*(*keyring).keys.offset(i as isize));
|
|
||||||
i += 1
|
|
||||||
}
|
|
||||||
free((*keyring).keys as *mut libc::c_void);
|
|
||||||
free(keyring as *mut libc::c_void);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* the reference counter of the key is increased by one */
|
|
||||||
pub unsafe fn dc_keyring_add(mut keyring: *mut dc_keyring_t, to_add: *mut dc_key_t) {
|
|
||||||
if keyring.is_null() || to_add.is_null() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (*keyring).count == (*keyring).allocated {
|
|
||||||
let newsize = (*keyring).allocated * 2 + 10;
|
|
||||||
(*keyring).keys = realloc(
|
|
||||||
(*keyring).keys as *mut libc::c_void,
|
|
||||||
(newsize as size_t).wrapping_mul(::std::mem::size_of::<*mut dc_key_t>()),
|
|
||||||
) as *mut *mut dc_key_t;
|
|
||||||
if (*keyring).keys.is_null() {
|
|
||||||
exit(41i32);
|
|
||||||
}
|
}
|
||||||
(*keyring).allocated = newsize
|
let stmt = dc_sqlite3_prepare(
|
||||||
}
|
context,
|
||||||
let ref mut fresh0 = *(*keyring).keys.offset((*keyring).count as isize);
|
sql,
|
||||||
*fresh0 = dc_key_ref(to_add);
|
b"SELECT private_key FROM keypairs ORDER BY addr=? DESC, is_default DESC;\x00"
|
||||||
(*keyring).count += 1;
|
as *const u8 as *const libc::c_char,
|
||||||
}
|
);
|
||||||
|
sqlite3_bind_text(stmt, 1, self_addr, -1, None);
|
||||||
// TODO should return bool? /rtn
|
while sqlite3_step(stmt) == 100 {
|
||||||
pub unsafe fn dc_keyring_load_self_private_for_decrypting(
|
if let Some(key) = Key::from_stmt(stmt, 0, 1) {
|
||||||
context: &dc_context_t,
|
self.add(key);
|
||||||
keyring: *mut dc_keyring_t,
|
}
|
||||||
self_addr: *const libc::c_char,
|
|
||||||
sql: &dc_sqlite3_t,
|
|
||||||
) -> libc::c_int {
|
|
||||||
// Can we prevent keyring and self_addr to be null?
|
|
||||||
if keyring.is_null() || self_addr.is_null() {
|
|
||||||
return 0i32;
|
|
||||||
}
|
|
||||||
let stmt: *mut sqlite3_stmt = dc_sqlite3_prepare(
|
|
||||||
context,
|
|
||||||
sql,
|
|
||||||
b"SELECT private_key FROM keypairs ORDER BY addr=? DESC, is_default DESC;\x00" as *const u8
|
|
||||||
as *const libc::c_char,
|
|
||||||
);
|
|
||||||
sqlite3_bind_text(stmt, 1i32, self_addr, -1i32, None);
|
|
||||||
while sqlite3_step(stmt) == 100i32 {
|
|
||||||
let key: *mut dc_key_t = dc_key_new();
|
|
||||||
if 0 != dc_key_set_from_stmt(key, stmt, 0i32, 1i32) {
|
|
||||||
dc_keyring_add(keyring, key);
|
|
||||||
}
|
}
|
||||||
dc_key_unref(key);
|
sqlite3_finalize(stmt);
|
||||||
}
|
|
||||||
sqlite3_finalize(stmt);
|
|
||||||
|
|
||||||
1
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -289,11 +289,7 @@ pub unsafe fn dc_pgp_calc_fingerprint(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO should return bool /rtn
|
// TODO should return bool /rtn
|
||||||
pub unsafe fn dc_pgp_split_key(
|
pub unsafe fn dc_pgp_split_key(context: &dc_context_t, private_in: *const dc_key_t) -> Option<Key> {
|
||||||
context: &dc_context_t,
|
|
||||||
private_in: *const dc_key_t,
|
|
||||||
ret_public_key: *mut dc_key_t,
|
|
||||||
) -> libc::c_int {
|
|
||||||
let mut success: libc::c_int = 0i32;
|
let mut success: libc::c_int = 0i32;
|
||||||
let mut key: *mut rpgp::signed_secret_key = 0 as *mut rpgp::signed_secret_key;
|
let mut key: *mut rpgp::signed_secret_key = 0 as *mut rpgp::signed_secret_key;
|
||||||
let mut pub_key: *mut rpgp::signed_public_key = 0 as *mut rpgp::signed_public_key;
|
let mut pub_key: *mut rpgp::signed_public_key = 0 as *mut rpgp::signed_public_key;
|
||||||
|
|||||||
@@ -2668,35 +2668,7 @@ unsafe fn stress_functions(context: &dc_context_t) {
|
|||||||
dc_key_unref(private_key2);
|
dc_key_unref(private_key2);
|
||||||
dc_key_unref(public_key);
|
dc_key_unref(public_key);
|
||||||
dc_key_unref(private_key);
|
dc_key_unref(private_key);
|
||||||
let fingerprint: *mut libc::c_char = dc_normalize_fingerprint(
|
|
||||||
b" 1234 567890 \n AbcD abcdef ABCDEF \x00" as *const u8 as *const libc::c_char,
|
|
||||||
);
|
|
||||||
if 0 != fingerprint.is_null() as libc::c_int as libc::c_long {
|
|
||||||
__assert_rtn(
|
|
||||||
(*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00"))
|
|
||||||
.as_ptr(),
|
|
||||||
b"../cmdline/stress.c\x00" as *const u8 as *const libc::c_char,
|
|
||||||
1076i32,
|
|
||||||
b"fingerprint\x00" as *const u8 as *const libc::c_char,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
};
|
|
||||||
if 0 != !(strcmp(
|
|
||||||
fingerprint,
|
|
||||||
b"1234567890ABCDABCDEFABCDEF\x00" as *const u8 as *const libc::c_char,
|
|
||||||
) == 0i32) as libc::c_int as libc::c_long
|
|
||||||
{
|
|
||||||
__assert_rtn(
|
|
||||||
(*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00"))
|
|
||||||
.as_ptr(),
|
|
||||||
b"../cmdline/stress.c\x00" as *const u8 as *const libc::c_char,
|
|
||||||
1077i32,
|
|
||||||
b"strcmp(fingerprint, \"1234567890ABCDABCDEFABCDEF\") == 0\x00" as *const u8
|
|
||||||
as *const libc::c_char,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
};
|
|
||||||
free(fingerprint as *mut libc::c_void);
|
|
||||||
if 0 != dc_is_configured(context) {
|
if 0 != dc_is_configured(context) {
|
||||||
let qr: *mut libc::c_char = dc_get_securejoin_qr(context, 0i32 as uint32_t);
|
let qr: *mut libc::c_char = dc_get_securejoin_qr(context, 0i32 as uint32_t);
|
||||||
if 0 != !(strlen(qr) > 55
|
if 0 != !(strlen(qr) > 55
|
||||||
|
|||||||
Reference in New Issue
Block a user