|
|
@ -9,32 +9,36 @@
|
|
|
|
#include <gcrypt.h>
|
|
|
|
#include <gcrypt.h>
|
|
|
|
#include <signal_protocol.h>
|
|
|
|
#include <signal_protocol.h>
|
|
|
|
#include <key_helper.h>
|
|
|
|
#include <key_helper.h>
|
|
|
|
|
|
|
|
#include <curve.h>
|
|
|
|
#include <lmdb.h>
|
|
|
|
#include <lmdb.h>
|
|
|
|
#include <strophe.h>
|
|
|
|
#include <strophe.h>
|
|
|
|
#include <weechat/weechat-plugin.h>
|
|
|
|
#include <weechat/weechat-plugin.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct t_omemo_db {
|
|
|
|
|
|
|
|
MDB_env *env;
|
|
|
|
|
|
|
|
MDB_dbi dbi_omemo;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#include "plugin.h"
|
|
|
|
#include "plugin.h"
|
|
|
|
#include "account.h"
|
|
|
|
#include "account.h"
|
|
|
|
#include "omemo.h"
|
|
|
|
#include "omemo.h"
|
|
|
|
|
|
|
|
|
|
|
|
const char *OMEMO_ADVICE = "[OMEMO encrypted message (XEP-0384)]";
|
|
|
|
#define mdb_val_str(s) { \
|
|
|
|
|
|
|
|
.mv_data = s, .mv_size = strlen(s), \
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
signal_type_base* signal_type_ref_vapi(void* instance) {
|
|
|
|
#define mdb_val_intptr(i) { \
|
|
|
|
if (!(instance != NULL))
|
|
|
|
.mv_data = i, .mv_size = sizeof(*i), \
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
signal_type_ref(instance);
|
|
|
|
|
|
|
|
return instance;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
signal_type_base* signal_type_unref_vapi(void* instance) {
|
|
|
|
#define mdb_val_sizeof(t) { \
|
|
|
|
if (!(instance != NULL))
|
|
|
|
.mv_data = NULL, .mv_size = sizeof(t), \
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
signal_type_unref(instance);
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const char *OMEMO_ADVICE = "[OMEMO encrypted message (XEP-0384)]";
|
|
|
|
|
|
|
|
|
|
|
|
void signal_protocol_address_free(signal_protocol_address* ptr) {
|
|
|
|
void signal_protocol_address_free(signal_protocol_address* ptr) {
|
|
|
|
if (!(ptr != NULL))
|
|
|
|
if (!ptr)
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
if (ptr->name) {
|
|
|
|
if (ptr->name) {
|
|
|
|
free((void*)ptr->name);
|
|
|
|
free((void*)ptr->name);
|
|
|
@ -43,9 +47,9 @@ void signal_protocol_address_free(signal_protocol_address* ptr) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void signal_protocol_address_set_name(signal_protocol_address* self, const char* name) {
|
|
|
|
void signal_protocol_address_set_name(signal_protocol_address* self, const char* name) {
|
|
|
|
if (!(self != NULL))
|
|
|
|
if (!self)
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
if (!(name != NULL))
|
|
|
|
if (!name)
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
char* n = malloc(strlen(name)+1);
|
|
|
|
char* n = malloc(strlen(name)+1);
|
|
|
|
memcpy(n, name, strlen(name));
|
|
|
|
memcpy(n, name, strlen(name));
|
|
|
@ -58,9 +62,9 @@ void signal_protocol_address_set_name(signal_protocol_address* self, const char*
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
char* signal_protocol_address_get_name(signal_protocol_address* self) {
|
|
|
|
char* signal_protocol_address_get_name(signal_protocol_address* self) {
|
|
|
|
if (!(self != NULL))
|
|
|
|
if (!self)
|
|
|
|
return NULL;
|
|
|
|
return NULL;
|
|
|
|
if (!(self->name != NULL))
|
|
|
|
if (!self->name)
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
char* res = malloc(sizeof(char) * (self->name_len + 1));
|
|
|
|
char* res = malloc(sizeof(char) * (self->name_len + 1));
|
|
|
|
memcpy(res, self->name, self->name_len);
|
|
|
|
memcpy(res, self->name, self->name_len);
|
|
|
@ -69,19 +73,19 @@ char* signal_protocol_address_get_name(signal_protocol_address* self) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int32_t signal_protocol_address_get_device_id(signal_protocol_address* self) {
|
|
|
|
int32_t signal_protocol_address_get_device_id(signal_protocol_address* self) {
|
|
|
|
if (!(self != NULL))
|
|
|
|
if (!self)
|
|
|
|
return -1;
|
|
|
|
return -1;
|
|
|
|
return self->device_id;
|
|
|
|
return self->device_id;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void signal_protocol_address_set_device_id(signal_protocol_address* self, int32_t device_id) {
|
|
|
|
void signal_protocol_address_set_device_id(signal_protocol_address* self, int32_t device_id) {
|
|
|
|
if (!(self != NULL))
|
|
|
|
if (!self)
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
self->device_id = device_id;
|
|
|
|
self->device_id = device_id;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
signal_protocol_address* signal_protocol_address_new(const char* name, int32_t device_id) {
|
|
|
|
signal_protocol_address* signal_protocol_address_new(const char* name, int32_t device_id) {
|
|
|
|
if (!(name != NULL))
|
|
|
|
if (!name)
|
|
|
|
return NULL;
|
|
|
|
return NULL;
|
|
|
|
signal_protocol_address* address = malloc(sizeof(signal_protocol_address));
|
|
|
|
signal_protocol_address* address = malloc(sizeof(signal_protocol_address));
|
|
|
|
address->device_id = -1;
|
|
|
|
address->device_id = -1;
|
|
|
@ -91,6 +95,43 @@ signal_protocol_address* signal_protocol_address_new(const char* name, int32_t d
|
|
|
|
return address;
|
|
|
|
return address;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int aes_cipher(int cipher, size_t key_len, int* algo, int* mode) {
|
|
|
|
|
|
|
|
switch (key_len) {
|
|
|
|
|
|
|
|
case 16:
|
|
|
|
|
|
|
|
*algo = GCRY_CIPHER_AES128;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 24:
|
|
|
|
|
|
|
|
*algo = GCRY_CIPHER_AES192;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 32:
|
|
|
|
|
|
|
|
*algo = GCRY_CIPHER_AES256;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
return SG_ERR_UNKNOWN;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (cipher) {
|
|
|
|
|
|
|
|
case SG_CIPHER_AES_CBC_PKCS5:
|
|
|
|
|
|
|
|
*mode = GCRY_CIPHER_MODE_CBC;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SG_CIPHER_AES_CTR_NOPADDING:
|
|
|
|
|
|
|
|
*mode = GCRY_CIPHER_MODE_CTR;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
return SG_ERR_UNKNOWN;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return SG_SUCCESS;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void lock_function(void *user_data)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
(void) user_data;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void unlock_function(void *user_data)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
(void) user_data;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int cp_randomize(uint8_t *data, size_t len) {
|
|
|
|
int cp_randomize(uint8_t *data, size_t len) {
|
|
|
|
gcry_randomize(data, len, GCRY_STRONG_RANDOM);
|
|
|
|
gcry_randomize(data, len, GCRY_STRONG_RANDOM);
|
|
|
|
return SG_SUCCESS;
|
|
|
|
return SG_SUCCESS;
|
|
|
@ -217,33 +258,6 @@ void cp_sha512_digest_cleanup(void *digest_context, void *user_data) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int aes_cipher(int cipher, size_t key_len, int* algo, int* mode) {
|
|
|
|
|
|
|
|
switch (key_len) {
|
|
|
|
|
|
|
|
case 16:
|
|
|
|
|
|
|
|
*algo = GCRY_CIPHER_AES128;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 24:
|
|
|
|
|
|
|
|
*algo = GCRY_CIPHER_AES192;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 32:
|
|
|
|
|
|
|
|
*algo = GCRY_CIPHER_AES256;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
return SG_ERR_UNKNOWN;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (cipher) {
|
|
|
|
|
|
|
|
case SG_CIPHER_AES_CBC_PKCS5:
|
|
|
|
|
|
|
|
*mode = GCRY_CIPHER_MODE_CBC;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SG_CIPHER_AES_CTR_NOPADDING:
|
|
|
|
|
|
|
|
*mode = GCRY_CIPHER_MODE_CTR;
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
return SG_ERR_UNKNOWN;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return SG_SUCCESS;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int cp_encrypt(signal_buffer **output,
|
|
|
|
int cp_encrypt(signal_buffer **output,
|
|
|
|
int cipher,
|
|
|
|
int cipher,
|
|
|
|
const uint8_t *key, size_t key_len,
|
|
|
|
const uint8_t *key, size_t key_len,
|
|
|
@ -391,70 +405,548 @@ no_error:
|
|
|
|
return SG_SUCCESS;
|
|
|
|
return SG_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void lock_function(void *user_data)
|
|
|
|
int iks_get_identity_key_pair(signal_buffer **public_data, signal_buffer **private_data, void *user_data)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
struct t_omemo *omemo = (struct t_omemo *)user_data;
|
|
|
|
|
|
|
|
MDB_txn *transaction;
|
|
|
|
|
|
|
|
MDB_val k_local_private_key = mdb_val_str("local_private_key");
|
|
|
|
|
|
|
|
MDB_val k_local_public_key = mdb_val_str("local_public_key");
|
|
|
|
|
|
|
|
MDB_val v_local_private_key, v_local_public_key;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Get the local client's identity key pair
|
|
|
|
|
|
|
|
if (mdb_txn_begin(omemo->db->env, NULL, MDB_RDONLY, &transaction)) {
|
|
|
|
|
|
|
|
weechat_printf(NULL, "%sxmpp: failed to open lmdb transaction",
|
|
|
|
|
|
|
|
weechat_prefix("error"));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mdb_get(transaction, omemo->db->dbi_omemo,
|
|
|
|
|
|
|
|
&k_local_private_key, &v_local_private_key) &&
|
|
|
|
|
|
|
|
mdb_get(transaction, omemo->db->dbi_omemo,
|
|
|
|
|
|
|
|
&k_local_public_key, &v_local_public_key))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
*private_data = signal_buffer_create(v_local_private_key.mv_data, v_local_private_key.mv_size);
|
|
|
|
|
|
|
|
*public_data = signal_buffer_create(v_local_public_key.mv_data, v_local_public_key.mv_size);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mdb_txn_commit(transaction)) {
|
|
|
|
|
|
|
|
weechat_printf(NULL, "%sxmpp: failed to write lmdb transaction",
|
|
|
|
|
|
|
|
weechat_prefix("error"));
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
struct ratchet_identity_key_pair *identity;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mdb_txn_abort(transaction);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mdb_txn_begin(omemo->db->env, NULL, 0, &transaction)) {
|
|
|
|
|
|
|
|
weechat_printf(NULL, "%sxmpp: failed to open lmdb transaction",
|
|
|
|
|
|
|
|
weechat_prefix("error"));
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
signal_protocol_key_helper_generate_identity_key_pair(
|
|
|
|
|
|
|
|
&identity, omemo->context);
|
|
|
|
|
|
|
|
ec_private_key *private_key = ratchet_identity_key_pair_get_private(identity);
|
|
|
|
|
|
|
|
ec_public_key *public_key = ratchet_identity_key_pair_get_public(identity);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ec_private_key_serialize(private_data, private_key);
|
|
|
|
|
|
|
|
ec_public_key_serialize(public_data, public_key);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
v_local_private_key.mv_data = signal_buffer_data(*private_data);
|
|
|
|
|
|
|
|
v_local_private_key.mv_size = signal_buffer_len(*private_data);
|
|
|
|
|
|
|
|
v_local_public_key.mv_data = signal_buffer_data(*public_data);
|
|
|
|
|
|
|
|
v_local_public_key.mv_size = signal_buffer_len(*public_data);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mdb_put(transaction, omemo->db->dbi_omemo,
|
|
|
|
|
|
|
|
&k_local_private_key, &v_local_private_key, MDB_NOOVERWRITE) &&
|
|
|
|
|
|
|
|
mdb_put(transaction, omemo->db->dbi_omemo,
|
|
|
|
|
|
|
|
&k_local_public_key, &v_local_public_key, MDB_NOOVERWRITE))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
weechat_printf(NULL, "%sxmpp: failed to write lmdb value",
|
|
|
|
|
|
|
|
weechat_prefix("error"));
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mdb_txn_commit(transaction)) {
|
|
|
|
|
|
|
|
weechat_printf(NULL, "%sxmpp: failed to write lmdb transaction",
|
|
|
|
|
|
|
|
weechat_prefix("error"));
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int iks_get_local_registration_id(void *user_data, uint32_t *registration_id)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
struct t_omemo *omemo = (struct t_omemo *)user_data;
|
|
|
|
|
|
|
|
MDB_txn *transaction;
|
|
|
|
|
|
|
|
MDB_val k_local_registration_id = mdb_val_str("local_registration_id");
|
|
|
|
|
|
|
|
MDB_val v_local_registration_id = mdb_val_sizeof(uint32_t);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Return the local client's registration ID
|
|
|
|
|
|
|
|
if (mdb_txn_begin(omemo->db->env, NULL, MDB_RDONLY, &transaction)) {
|
|
|
|
|
|
|
|
weechat_printf(NULL, "%sxmpp: failed to open lmdb transaction",
|
|
|
|
|
|
|
|
weechat_prefix("error"));
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mdb_get(transaction, omemo->db->dbi_omemo,
|
|
|
|
|
|
|
|
&k_local_registration_id,
|
|
|
|
|
|
|
|
&v_local_registration_id))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
*registration_id = *(uint32_t*)v_local_registration_id.mv_data;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mdb_txn_commit(transaction)) {
|
|
|
|
|
|
|
|
weechat_printf(NULL, "%sxmpp: failed to write lmdb transaction",
|
|
|
|
|
|
|
|
weechat_prefix("error"));
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
mdb_txn_abort(transaction);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mdb_txn_begin(omemo->db->env, NULL, 0, &transaction)) {
|
|
|
|
|
|
|
|
weechat_printf(NULL, "%sxmpp: failed to open lmdb transaction",
|
|
|
|
|
|
|
|
weechat_prefix("error"));
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
signal_protocol_key_helper_generate_registration_id(
|
|
|
|
|
|
|
|
(uint32_t*)&v_local_registration_id.mv_data, 0, omemo->context);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mdb_put(transaction, omemo->db->dbi_omemo,
|
|
|
|
|
|
|
|
&k_local_registration_id,
|
|
|
|
|
|
|
|
&v_local_registration_id, MDB_NOOVERWRITE))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
weechat_printf(NULL, "%sxmpp: failed to write lmdb value",
|
|
|
|
|
|
|
|
weechat_prefix("error"));
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mdb_txn_commit(transaction)) {
|
|
|
|
|
|
|
|
weechat_printf(NULL, "%sxmpp: failed to write lmdb transaction",
|
|
|
|
|
|
|
|
weechat_prefix("error"));
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int iks_save_identity(const signal_protocol_address *address, uint8_t *key_data, size_t key_len, void *user_data)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
struct t_omemo *omemo = (struct t_omemo *)user_data;
|
|
|
|
|
|
|
|
MDB_txn *transaction;
|
|
|
|
|
|
|
|
MDB_val k_registration_id = {
|
|
|
|
|
|
|
|
.mv_data = NULL,
|
|
|
|
|
|
|
|
.mv_size = strlen("registration_id_") + address->name_len,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
MDB_val v_registration_id = mdb_val_intptr((uint32_t*)&address->device_id);
|
|
|
|
|
|
|
|
MDB_val k_identity_key = {
|
|
|
|
|
|
|
|
.mv_data = NULL,
|
|
|
|
|
|
|
|
.mv_size = strlen("identity_key_") + address->name_len,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
MDB_val v_identity_key = {.mv_data = key_data, .mv_size = key_len};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
k_registration_id.mv_data = malloc(sizeof(char) * (
|
|
|
|
|
|
|
|
k_registration_id.mv_size + 1));
|
|
|
|
|
|
|
|
snprintf(k_registration_id.mv_data, k_registration_id.mv_size,
|
|
|
|
|
|
|
|
"registration_id_%s", address->name);
|
|
|
|
|
|
|
|
k_identity_key.mv_data = malloc(sizeof(char) * (
|
|
|
|
|
|
|
|
k_identity_key.mv_size + 1));
|
|
|
|
|
|
|
|
snprintf(k_identity_key.mv_data, k_identity_key.mv_size,
|
|
|
|
|
|
|
|
"identity_key_%s", address->name);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Save a remote client's identity key
|
|
|
|
|
|
|
|
if (mdb_txn_begin(omemo->db->env, NULL, 0, &transaction)) {
|
|
|
|
|
|
|
|
weechat_printf(NULL, "%sxmpp: failed to open lmdb transaction",
|
|
|
|
|
|
|
|
weechat_prefix("error"));
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mdb_put(transaction, omemo->db->dbi_omemo, &k_registration_id,
|
|
|
|
|
|
|
|
&v_registration_id, 0) ||
|
|
|
|
|
|
|
|
mdb_put(transaction, omemo->db->dbi_omemo, &k_identity_key,
|
|
|
|
|
|
|
|
&v_identity_key, 0)) {
|
|
|
|
|
|
|
|
weechat_printf(NULL, "%sxmpp: failed to write lmdb value",
|
|
|
|
|
|
|
|
weechat_prefix("error"));
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mdb_txn_commit(transaction)) {
|
|
|
|
|
|
|
|
weechat_printf(NULL, "%sxmpp: failed to write lmdb transaction",
|
|
|
|
|
|
|
|
weechat_prefix("error"));
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int iks_is_trusted_identity(const signal_protocol_address *address, uint8_t *key_data, size_t key_len, void *user_data)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
struct t_omemo *omemo = (struct t_omemo *)user_data;
|
|
|
|
|
|
|
|
MDB_txn *transaction;
|
|
|
|
|
|
|
|
MDB_val k_registration_id = {
|
|
|
|
|
|
|
|
.mv_data = NULL,
|
|
|
|
|
|
|
|
.mv_size = strlen("registration_id_") + address->name_len,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
MDB_val v_registration_id = mdb_val_intptr((uint32_t*)&address->device_id);
|
|
|
|
|
|
|
|
MDB_val k_identity_key = {
|
|
|
|
|
|
|
|
.mv_data = NULL,
|
|
|
|
|
|
|
|
.mv_size = strlen("identity_key_") + address->name_len,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
MDB_val v_identity_key = {.mv_data = key_data, .mv_size = key_len};
|
|
|
|
|
|
|
|
int trusted = 1;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
k_registration_id.mv_data = malloc(sizeof(char) * (
|
|
|
|
|
|
|
|
k_registration_id.mv_size + 1));
|
|
|
|
|
|
|
|
snprintf(k_registration_id.mv_data, k_registration_id.mv_size,
|
|
|
|
|
|
|
|
"registration_id_%s", address->name);
|
|
|
|
|
|
|
|
k_identity_key.mv_data = malloc(sizeof(char) * (
|
|
|
|
|
|
|
|
k_identity_key.mv_size + 1));
|
|
|
|
|
|
|
|
snprintf(k_identity_key.mv_data, k_identity_key.mv_size,
|
|
|
|
|
|
|
|
"identity_key_%s", address->name);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Verify a remote client's identity key
|
|
|
|
|
|
|
|
if (mdb_txn_begin(omemo->db->env, NULL, MDB_RDONLY, &transaction)) {
|
|
|
|
|
|
|
|
weechat_printf(NULL, "%sxmpp: failed to open lmdb transaction",
|
|
|
|
|
|
|
|
weechat_prefix("error"));
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mdb_get(transaction, omemo->db->dbi_omemo, &k_registration_id,
|
|
|
|
|
|
|
|
&v_registration_id) ||
|
|
|
|
|
|
|
|
mdb_get(transaction, omemo->db->dbi_omemo, &k_identity_key,
|
|
|
|
|
|
|
|
&v_identity_key)) {
|
|
|
|
|
|
|
|
weechat_printf(NULL, "%sxmpp: failed to write lmdb value",
|
|
|
|
|
|
|
|
weechat_prefix("error"));
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (*(uint32_t*)v_registration_id.mv_data != (uint32_t)address->device_id)
|
|
|
|
|
|
|
|
trusted = 0;
|
|
|
|
|
|
|
|
if (v_identity_key.mv_size != key_len ||
|
|
|
|
|
|
|
|
memcmp(v_identity_key.mv_data, key_data, key_len) != 0)
|
|
|
|
|
|
|
|
trusted = 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mdb_txn_commit(transaction)) {
|
|
|
|
|
|
|
|
weechat_printf(NULL, "%sxmpp: failed to write lmdb transaction",
|
|
|
|
|
|
|
|
weechat_prefix("error"));
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return trusted;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void iks_destroy_func(void *user_data)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
struct t_omemo *omemo = (struct t_omemo *)user_data;
|
|
|
|
|
|
|
|
(void) omemo;
|
|
|
|
|
|
|
|
// Function called to perform cleanup when the data store context is being destroyed
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int pks_load_pre_key(signal_buffer **record, uint32_t pre_key_id, void *user_data)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
struct t_omemo *omemo = (struct t_omemo *)user_data;
|
|
|
|
|
|
|
|
MDB_txn *transaction;
|
|
|
|
|
|
|
|
MDB_val k_pre_key = mdb_val_str("pre_key");
|
|
|
|
|
|
|
|
MDB_val v_pre_key;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mdb_txn_begin(omemo->db->env, NULL, MDB_RDONLY, &transaction)) {
|
|
|
|
|
|
|
|
weechat_printf(NULL, "%sxmpp: failed to open lmdb transaction",
|
|
|
|
|
|
|
|
weechat_prefix("error"));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mdb_get(transaction, omemo->db->dbi_omemo,
|
|
|
|
|
|
|
|
&k_pre_key, &v_pre_key))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
*record = signal_buffer_create(v_pre_key.mv_data, v_pre_key.mv_size);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mdb_txn_commit(transaction)) {
|
|
|
|
|
|
|
|
weechat_printf(NULL, "%sxmpp: failed to close lmdb transaction",
|
|
|
|
|
|
|
|
weechat_prefix("error"));
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
signal_protocol_key_helper_pre_key_list_node *pre_keys_list;
|
|
|
|
|
|
|
|
session_pre_key *pre_key = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mdb_txn_abort(transaction);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
signal_protocol_key_helper_generate_pre_keys(
|
|
|
|
|
|
|
|
&pre_keys_list, 0, 100, omemo->context);
|
|
|
|
|
|
|
|
pre_key = signal_protocol_key_helper_key_list_element(pre_keys_list);
|
|
|
|
|
|
|
|
signal_protocol_key_helper_key_list_next(pre_keys_list);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t id = session_pre_key_get_id(pre_key);
|
|
|
|
|
|
|
|
session_pre_key_serialize(&record, pre_key);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
signal_protocol_key_helper_key_list_free(pre_keys_list);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mdb_txn_begin(omemo->db->env, NULL, 0, &transaction)) {
|
|
|
|
|
|
|
|
weechat_printf(NULL, "%sxmpp: failed to open lmdb transaction",
|
|
|
|
|
|
|
|
weechat_prefix("error"));
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
v_pre_key.mv_data = signal_buffer_data(*record);
|
|
|
|
|
|
|
|
v_pre_key.mv_size = signal_buffer_len(*record);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mdb_put(transaction, omemo->db->dbi_omemo,
|
|
|
|
|
|
|
|
&k_pre_key, &v_pre_key, MDB_NOOVERWRITE))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
weechat_printf(NULL, "%sxmpp: failed to write lmdb value",
|
|
|
|
|
|
|
|
weechat_prefix("error"));
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mdb_txn_commit(transaction)) {
|
|
|
|
|
|
|
|
weechat_printf(NULL, "%sxmpp: failed to write lmdb transaction",
|
|
|
|
|
|
|
|
weechat_prefix("error"));
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int pks_store_pre_key(uint32_t pre_key_id, uint8_t *record, size_t record_len, void *user_data)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
(void) pre_key_id;
|
|
|
|
|
|
|
|
(void) record;
|
|
|
|
|
|
|
|
(void) record_len;
|
|
|
|
(void) user_data;
|
|
|
|
(void) user_data;
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
struct t_omemo *omemo = (struct t_omemo *)user_data;
|
|
|
|
|
|
|
|
MDB_txn *transaction;
|
|
|
|
|
|
|
|
MDB_val k_pre_key = mdb_val_str("pre_key");
|
|
|
|
|
|
|
|
MDB_val v_pre_key;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mdb_txn_begin(omemo->db->env, NULL, MDB_RDONLY, &transaction)) {
|
|
|
|
|
|
|
|
weechat_printf(NULL, "%sxmpp: failed to open lmdb transaction",
|
|
|
|
|
|
|
|
weechat_prefix("error"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void unlock_function(void *user_data)
|
|
|
|
if (mdb_get(transaction, omemo->db->dbi_omemo,
|
|
|
|
|
|
|
|
&k_pre_key, &v_pre_key))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
*record = signal_buffer_create(v_pre_key.mv_data, v_pre_key.mv_size);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mdb_txn_commit(transaction)) {
|
|
|
|
|
|
|
|
weechat_printf(NULL, "%sxmpp: failed to close lmdb transaction",
|
|
|
|
|
|
|
|
weechat_prefix("error"));
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
signal_protocol_key_helper_pre_key_list_node *pre_keys_list;
|
|
|
|
|
|
|
|
session_pre_key *pre_key = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mdb_txn_abort(transaction);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
signal_protocol_key_helper_generate_pre_keys(
|
|
|
|
|
|
|
|
&pre_keys_list, 0, 100, omemo->context);
|
|
|
|
|
|
|
|
pre_key = signal_protocol_key_helper_key_list_element(pre_keys_list);
|
|
|
|
|
|
|
|
signal_protocol_key_helper_key_list_next(pre_keys_list);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t id = session_pre_key_get_id(pre_key);
|
|
|
|
|
|
|
|
session_pre_key_serialize(&record, pre_key);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
signal_protocol_key_helper_key_list_free(pre_keys_list);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mdb_txn_begin(omemo->db->env, NULL, 0, &transaction)) {
|
|
|
|
|
|
|
|
weechat_printf(NULL, "%sxmpp: failed to open lmdb transaction",
|
|
|
|
|
|
|
|
weechat_prefix("error"));
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
v_pre_key.mv_data = signal_buffer_data(*record);
|
|
|
|
|
|
|
|
v_pre_key.mv_size = signal_buffer_len(*record);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mdb_put(transaction, omemo->db->dbi_omemo,
|
|
|
|
|
|
|
|
&k_pre_key, &v_pre_key, MDB_NOOVERWRITE))
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
weechat_printf(NULL, "%sxmpp: failed to write lmdb value",
|
|
|
|
|
|
|
|
weechat_prefix("error"));
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mdb_txn_commit(transaction)) {
|
|
|
|
|
|
|
|
weechat_printf(NULL, "%sxmpp: failed to write lmdb transaction",
|
|
|
|
|
|
|
|
weechat_prefix("error"));
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int pks_contains_pre_key(uint32_t pre_key_id, void *user_data)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
(void) pre_key_id;
|
|
|
|
(void) user_data;
|
|
|
|
(void) user_data;
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void omemo__log_emit_weechat(int level, const char *message, size_t len, void *user_data)
|
|
|
|
int pks_remove_pre_key(uint32_t pre_key_id, void *user_data)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
struct t_gui_buffer *buffer = (struct t_gui_buffer*)user_data;
|
|
|
|
(void) pre_key_id;
|
|
|
|
|
|
|
|
(void) user_data;
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static const char *log_level_name[5] = {"error", "warn", "notice", "info", "debug"};
|
|
|
|
void pks_destroy_func(void *user_data)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
(void) user_data;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const char *tags = level < SG_LOG_DEBUG ? "no_log" : NULL;
|
|
|
|
int spks_load_signed_pre_key(signal_buffer **record, uint32_t signed_pre_key_id, void *user_data)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
(void) record;
|
|
|
|
|
|
|
|
(void) signed_pre_key_id;
|
|
|
|
|
|
|
|
(void) user_data;
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
//session_signed_pre_key *signed_pre_key;
|
|
|
|
|
|
|
|
//int start_id = 0;
|
|
|
|
|
|
|
|
//time_t timestamp = time(NULL);
|
|
|
|
|
|
|
|
//signal_protocol_key_helper_generate_signed_pre_key(&signed_pre_key, new_omemo->identity, 5, timestamp, new_omemo->context);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
weechat_printf_date_tags(
|
|
|
|
int spks_store_signed_pre_key(uint32_t signed_pre_key_id, uint8_t *record, size_t record_len, void *user_data)
|
|
|
|
buffer, 0, tags,
|
|
|
|
{
|
|
|
|
_("%somemo (%s): %.*s"),
|
|
|
|
(void) signed_pre_key_id;
|
|
|
|
weechat_prefix("network"),
|
|
|
|
(void) record;
|
|
|
|
log_level_name[level], len, message);
|
|
|
|
(void) record_len;
|
|
|
|
|
|
|
|
(void) user_data;
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int iks_get_identity_key_pair(signal_buffer **public_data, signal_buffer **private_data, void *user_data)
|
|
|
|
int spks_contains_signed_pre_key(uint32_t signed_pre_key_id, void *user_data)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
(void) public_data;
|
|
|
|
(void) signed_pre_key_id;
|
|
|
|
(void) private_data;
|
|
|
|
|
|
|
|
(void) user_data;
|
|
|
|
(void) user_data;
|
|
|
|
// Get the local client's identity key pair
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int iks_get_local_registration_id(void *user_data, uint32_t *registration_id)
|
|
|
|
int spks_remove_signed_pre_key(uint32_t signed_pre_key_id, void *user_data)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
(void) signed_pre_key_id;
|
|
|
|
(void) user_data;
|
|
|
|
(void) user_data;
|
|
|
|
(void) registration_id;
|
|
|
|
return -1;
|
|
|
|
// Return the local client's registration ID
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int iks_save_identity(const signal_protocol_address *address, uint8_t *key_data, size_t key_len, void *user_data)
|
|
|
|
void spks_destroy_func(void *user_data)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
(void) user_data;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int ss_load_session_func(signal_buffer **record, signal_buffer **user_record, const signal_protocol_address *address, void *user_data)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
(void) record;
|
|
|
|
|
|
|
|
(void) user_record;
|
|
|
|
(void) address;
|
|
|
|
(void) address;
|
|
|
|
(void) key_data;
|
|
|
|
|
|
|
|
(void) key_len;
|
|
|
|
|
|
|
|
(void) user_data;
|
|
|
|
(void) user_data;
|
|
|
|
// Save a remote client's identity key
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int iks_is_trusted_identity(const signal_protocol_address *address, uint8_t *key_data, size_t key_len, void *user_data)
|
|
|
|
int ss_get_sub_device_sessions_func(signal_int_list **sessions, const char *name, size_t name_len, void *user_data)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
(void) sessions;
|
|
|
|
|
|
|
|
(void) name;
|
|
|
|
|
|
|
|
(void) name_len;
|
|
|
|
|
|
|
|
(void) user_data;
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int ss_store_session_func(const signal_protocol_address *address, uint8_t *record, size_t record_len, uint8_t *user_record, size_t user_record_len, void *user_data)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
(void) address;
|
|
|
|
(void) address;
|
|
|
|
(void) key_data;
|
|
|
|
(void) record;
|
|
|
|
(void) key_len;
|
|
|
|
(void) record_len;
|
|
|
|
|
|
|
|
(void) user_record;
|
|
|
|
|
|
|
|
(void) user_record_len;
|
|
|
|
(void) user_data;
|
|
|
|
(void) user_data;
|
|
|
|
// Verify a remote client's identity key
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void iks_destroy_func(void *user_data)
|
|
|
|
int ss_contains_session_func(const signal_protocol_address *address, void *user_data)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
(void) address;
|
|
|
|
(void) user_data;
|
|
|
|
(void) user_data;
|
|
|
|
// Function called to perform cleanup when the data store context is being destroyed
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int ss_delete_session_func(const signal_protocol_address *address, void *user_data)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
(void) address;
|
|
|
|
|
|
|
|
(void) user_data;
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int ss_delete_all_sessions_func(const char *name, size_t name_len, void *user_data)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
(void) name;
|
|
|
|
|
|
|
|
(void) name_len;
|
|
|
|
|
|
|
|
(void) user_data;
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void ss_destroy_func(void *user_data)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
(void) user_data;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int sks_store_sender_key(const signal_protocol_sender_key_name *sender_key_name, uint8_t *record, size_t record_len, uint8_t *user_record, size_t user_record_len, void *user_data)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
(void) sender_key_name;
|
|
|
|
|
|
|
|
(void) record;
|
|
|
|
|
|
|
|
(void) record_len;
|
|
|
|
|
|
|
|
(void) user_record;
|
|
|
|
|
|
|
|
(void) user_record_len;
|
|
|
|
|
|
|
|
(void) user_data;
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int sks_load_sender_key(signal_buffer **record, signal_buffer **user_record, const signal_protocol_sender_key_name *sender_key_name, void *user_data)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
(void) record;
|
|
|
|
|
|
|
|
(void) user_record;
|
|
|
|
|
|
|
|
(void) sender_key_name;
|
|
|
|
|
|
|
|
(void) user_data;
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void sks_destroy_func(void *user_data)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
(void) user_data;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void omemo__log_emit_weechat(int level, const char *message, size_t len, void *user_data)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
struct t_gui_buffer *buffer = (struct t_gui_buffer*)user_data;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static const char *log_level_name[5] = {"error", "warn", "notice", "info", "debug"};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const char *tags = level < SG_LOG_DEBUG ? "no_log" : NULL;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
weechat_printf_date_tags(
|
|
|
|
|
|
|
|
buffer, 0, tags,
|
|
|
|
|
|
|
|
_("%somemo (%s): %.*s"),
|
|
|
|
|
|
|
|
weechat_prefix("network"),
|
|
|
|
|
|
|
|
log_level_name[level], len, message);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void omemo__init(struct t_gui_buffer *buffer, struct t_omemo **omemo,
|
|
|
|
void omemo__init(struct t_gui_buffer *buffer, struct t_omemo **omemo,
|
|
|
|
const char *account_name)
|
|
|
|
const char *account_name)
|
|
|
@ -465,15 +957,17 @@ void omemo__init(struct t_gui_buffer *buffer, struct t_omemo **omemo,
|
|
|
|
|
|
|
|
|
|
|
|
new_omemo = calloc(1, sizeof(**omemo));
|
|
|
|
new_omemo = calloc(1, sizeof(**omemo));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
new_omemo->db = malloc(sizeof(struct t_omemo_db));
|
|
|
|
|
|
|
|
|
|
|
|
signal_context_create(&new_omemo->context, buffer);
|
|
|
|
signal_context_create(&new_omemo->context, buffer);
|
|
|
|
signal_context_set_log_function(new_omemo->context, &omemo__log_emit_weechat);
|
|
|
|
signal_context_set_log_function(new_omemo->context, &omemo__log_emit_weechat);
|
|
|
|
|
|
|
|
|
|
|
|
mdb_env_create(&new_omemo->db.env);
|
|
|
|
mdb_env_create(&new_omemo->db->env);
|
|
|
|
mdb_env_set_maxdbs(new_omemo->db.env, 50);
|
|
|
|
mdb_env_set_maxdbs(new_omemo->db->env, 50);
|
|
|
|
mdb_env_set_mapsize(new_omemo->db.env, (size_t)1048576 * 100000); // 1MB * 100000
|
|
|
|
mdb_env_set_mapsize(new_omemo->db->env, (size_t)1048576 * 100000); // 1MB * 100000
|
|
|
|
char *path = weechat_string_eval_expression("${weechat_data_dir}/xmpp.omemo.db",
|
|
|
|
char *path = weechat_string_eval_expression("${weechat_data_dir}/xmpp.omemo.db",
|
|
|
|
NULL, NULL, NULL);
|
|
|
|
NULL, NULL, NULL);
|
|
|
|
if (mdb_env_open(new_omemo->db.env, path, MDB_NOSUBDIR, 0664) != 0)
|
|
|
|
if (mdb_env_open(new_omemo->db->env, path, MDB_NOSUBDIR, 0664) != 0)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -481,19 +975,20 @@ void omemo__init(struct t_gui_buffer *buffer, struct t_omemo **omemo,
|
|
|
|
|
|
|
|
|
|
|
|
MDB_txn *parentTransaction = NULL;
|
|
|
|
MDB_txn *parentTransaction = NULL;
|
|
|
|
MDB_txn *transaction;
|
|
|
|
MDB_txn *transaction;
|
|
|
|
if (mdb_txn_begin(new_omemo->db.env, parentTransaction, 0 ? MDB_RDONLY : 0, &transaction)) {
|
|
|
|
if (mdb_txn_begin(new_omemo->db->env, parentTransaction, 0 ? MDB_RDONLY : 0, &transaction)) {
|
|
|
|
//Error
|
|
|
|
weechat_printf(NULL, "%sxmpp: failed to open lmdb transaction",
|
|
|
|
|
|
|
|
weechat_prefix("error"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (0) {
|
|
|
|
size_t db_name_len = strlen("omemo_") + strlen(account_name);
|
|
|
|
mdb_txn_abort(transaction);
|
|
|
|
char *db_name = malloc(sizeof(char) * (db_name_len + 1));
|
|
|
|
} else {
|
|
|
|
snprintf(db_name, db_name_len+1, "identity_key_%s", account_name);
|
|
|
|
mdb_txn_commit(transaction);
|
|
|
|
if (mdb_dbi_open(transaction, db_name, MDB_DUPSORT | MDB_CREATE, &new_omemo->db->dbi_omemo)) {
|
|
|
|
|
|
|
|
weechat_printf(NULL, "%sxmpp: failed to open lmdb database",
|
|
|
|
|
|
|
|
weechat_prefix("error"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (mdb_dbi_open(transaction, "databasename", MDB_DUPSORT | MDB_CREATE, new_omemo->db.dbi)) {
|
|
|
|
mdb_txn_abort(transaction);
|
|
|
|
//Error
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct signal_crypto_provider crypto_provider = {
|
|
|
|
struct signal_crypto_provider crypto_provider = {
|
|
|
|
.random_func = &cp_random_generator,
|
|
|
|
.random_func = &cp_random_generator,
|
|
|
@ -507,28 +1002,12 @@ void omemo__init(struct t_gui_buffer *buffer, struct t_omemo **omemo,
|
|
|
|
.sha512_digest_cleanup_func = &cp_sha512_digest_cleanup,
|
|
|
|
.sha512_digest_cleanup_func = &cp_sha512_digest_cleanup,
|
|
|
|
.encrypt_func = &cp_encrypt,
|
|
|
|
.encrypt_func = &cp_encrypt,
|
|
|
|
.decrypt_func = &cp_decrypt,
|
|
|
|
.decrypt_func = &cp_decrypt,
|
|
|
|
.user_data = buffer,
|
|
|
|
.user_data = new_omemo,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
signal_context_set_crypto_provider(new_omemo->context, &crypto_provider);
|
|
|
|
signal_context_set_crypto_provider(new_omemo->context, &crypto_provider);
|
|
|
|
signal_context_set_locking_functions(new_omemo->context, &lock_function, &unlock_function);
|
|
|
|
signal_context_set_locking_functions(new_omemo->context, &lock_function, &unlock_function);
|
|
|
|
|
|
|
|
|
|
|
|
signal_protocol_key_helper_pre_key_list_node *pre_keys_head;
|
|
|
|
|
|
|
|
session_signed_pre_key *signed_pre_key;
|
|
|
|
|
|
|
|
int start_id = 0;
|
|
|
|
|
|
|
|
time_t timestamp = time(NULL);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (new_omemo->identity)
|
|
|
|
|
|
|
|
0;
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
signal_protocol_key_helper_generate_identity_key_pair(&new_omemo->identity, new_omemo->context);
|
|
|
|
|
|
|
|
signal_protocol_key_helper_generate_registration_id(&new_omemo->device_id, 0, new_omemo->context);
|
|
|
|
|
|
|
|
signal_protocol_key_helper_generate_pre_keys(&pre_keys_head, start_id, 100, new_omemo->context);
|
|
|
|
|
|
|
|
signal_protocol_key_helper_generate_signed_pre_key(&signed_pre_key, new_omemo->identity, 5, timestamp, new_omemo->context);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Store pre keys in the pre key store. */
|
|
|
|
|
|
|
|
/* Store signed pre key in the signed pre key store. */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
signal_protocol_store_context_create(&new_omemo->store_context, new_omemo->context);
|
|
|
|
signal_protocol_store_context_create(&new_omemo->store_context, new_omemo->context);
|
|
|
|
|
|
|
|
|
|
|
|
struct signal_protocol_identity_key_store identity_key_store = {
|
|
|
|
struct signal_protocol_identity_key_store identity_key_store = {
|
|
|
@ -537,10 +1016,59 @@ void omemo__init(struct t_gui_buffer *buffer, struct t_omemo **omemo,
|
|
|
|
.save_identity = &iks_save_identity,
|
|
|
|
.save_identity = &iks_save_identity,
|
|
|
|
.is_trusted_identity = &iks_is_trusted_identity,
|
|
|
|
.is_trusted_identity = &iks_is_trusted_identity,
|
|
|
|
.destroy_func = &iks_destroy_func,
|
|
|
|
.destroy_func = &iks_destroy_func,
|
|
|
|
.user_data = account_name,
|
|
|
|
.user_data = new_omemo,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
signal_protocol_store_context_set_identity_key_store(
|
|
|
|
|
|
|
|
new_omemo->store_context, &identity_key_store);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct signal_protocol_pre_key_store pre_key_store = {
|
|
|
|
|
|
|
|
.load_pre_key = &pks_load_pre_key,
|
|
|
|
|
|
|
|
.store_pre_key = &pks_store_pre_key,
|
|
|
|
|
|
|
|
.contains_pre_key = &pks_contains_pre_key,
|
|
|
|
|
|
|
|
.remove_pre_key = &pks_remove_pre_key,
|
|
|
|
|
|
|
|
.destroy_func = &pks_destroy_func,
|
|
|
|
|
|
|
|
.user_data = new_omemo,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
signal_protocol_store_context_set_pre_key_store(
|
|
|
|
|
|
|
|
new_omemo->store_context, &pre_key_store);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct signal_protocol_signed_pre_key_store signed_pre_key_store = {
|
|
|
|
|
|
|
|
.load_signed_pre_key = &spks_load_signed_pre_key,
|
|
|
|
|
|
|
|
.store_signed_pre_key = &spks_store_signed_pre_key,
|
|
|
|
|
|
|
|
.contains_signed_pre_key = &spks_contains_signed_pre_key,
|
|
|
|
|
|
|
|
.remove_signed_pre_key = &spks_remove_signed_pre_key,
|
|
|
|
|
|
|
|
.destroy_func = &spks_destroy_func,
|
|
|
|
|
|
|
|
.user_data = new_omemo,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
signal_protocol_store_context_set_signed_pre_key_store(
|
|
|
|
|
|
|
|
new_omemo->store_context, &signed_pre_key_store);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct signal_protocol_session_store session_store = {
|
|
|
|
|
|
|
|
.load_session_func = &ss_load_session_func,
|
|
|
|
|
|
|
|
.get_sub_device_sessions_func = &ss_get_sub_device_sessions_func,
|
|
|
|
|
|
|
|
.store_session_func = &ss_store_session_func,
|
|
|
|
|
|
|
|
.contains_session_func = &ss_contains_session_func,
|
|
|
|
|
|
|
|
.delete_session_func = &ss_delete_session_func,
|
|
|
|
|
|
|
|
.delete_all_sessions_func = &ss_delete_all_sessions_func,
|
|
|
|
|
|
|
|
.destroy_func = &ss_destroy_func,
|
|
|
|
|
|
|
|
.user_data = new_omemo,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
signal_protocol_store_context_set_session_store(
|
|
|
|
|
|
|
|
new_omemo->store_context, &session_store);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct signal_protocol_sender_key_store sender_key_store = {
|
|
|
|
|
|
|
|
.store_sender_key = &sks_store_sender_key,
|
|
|
|
|
|
|
|
.load_sender_key = &sks_load_sender_key,
|
|
|
|
|
|
|
|
.destroy_func = &sks_destroy_func,
|
|
|
|
|
|
|
|
.user_data = new_omemo,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
signal_protocol_store_context_set_identity_key_store(new_omemo->store_context, &identity_key_store);
|
|
|
|
signal_protocol_store_context_set_sender_key_store(
|
|
|
|
|
|
|
|
new_omemo->store_context, &sender_key_store);
|
|
|
|
|
|
|
|
|
|
|
|
*omemo = new_omemo;
|
|
|
|
*omemo = new_omemo;
|
|
|
|
}
|
|
|
|
}
|
|
|
|