Added callbacks in im encryption engine for decrypting incoming files in chat messages + improved lime test to check decrypted file is equal to sent one

This commit is contained in:
Sylvain Berfini 2016-11-07 16:32:09 +01:00
parent 28d5816c06
commit c284239d54
8 changed files with 139 additions and 46 deletions

View file

@ -323,7 +323,10 @@ const LinphoneContent *linphone_chat_message_get_file_transfer_information(const
static void on_recv_body(belle_sip_user_body_handler_t *bh, belle_sip_message_t *m, void *data, size_t offset,
const uint8_t *buffer, size_t size) {
LinphoneChatMessage *msg = (LinphoneChatMessage *)data;
LinphoneCore *lc;
LinphoneCore *lc = NULL;
LinphoneImEncryptionEngine *imee = NULL;
int retval = -1;
char *decrypted_buffer = NULL;
if (!msg->chat_room) {
linphone_chat_message_cancel_file_transfer(msg);
@ -344,33 +347,33 @@ static void on_recv_body(belle_sip_user_body_handler_t *bh, belle_sip_message_t
if (size == 0) {
return;
}
if (linphone_content_get_key(msg->file_transfer_information) !=
NULL) { /* we have a key, we must decrypt the file */
/* get data from callback to a plainBuffer */
char *plainBuffer = (char *)ms_malloc0(size);
lime_decryptFile(linphone_content_get_cryptoContext_address(msg->file_transfer_information),
(unsigned char *)linphone_content_get_key(msg->file_transfer_information), size, plainBuffer,
(char *)buffer);
if (linphone_chat_message_cbs_get_file_transfer_recv(msg->callbacks)) {
LinphoneBuffer *lb = linphone_buffer_new_from_data((unsigned char *)plainBuffer, size);
linphone_chat_message_cbs_get_file_transfer_recv(msg->callbacks)(msg, msg->file_transfer_information, lb);
linphone_buffer_unref(lb);
} else {
/* legacy: call back given by application level */
linphone_core_notify_file_transfer_recv(lc, msg, msg->file_transfer_information, plainBuffer, size);
decrypted_buffer = (char *)ms_malloc0(size);
imee = linphone_core_get_im_encryption_engine(lc);
if (imee) {
LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee);
LinphoneImEncryptionEngineDownloadingFileBufferCb cb_process_downloading_file_buffer = linphone_im_encryption_engine_cbs_get_process_downloading_file_buffer(imee_cbs);
if (cb_process_downloading_file_buffer) {
retval = cb_process_downloading_file_buffer(lc, msg, (const char *)buffer, size, &decrypted_buffer);
}
ms_free(plainBuffer);
} else { /* regular file, no deciphering */
}
if (retval <= 0) {
const uint8_t *buffer_to_use = buffer;
if (retval == 0) {
buffer_to_use = (const uint8_t *)decrypted_buffer;
}
if (linphone_chat_message_cbs_get_file_transfer_recv(msg->callbacks)) {
LinphoneBuffer *lb = linphone_buffer_new_from_data(buffer, size);
LinphoneBuffer *lb = linphone_buffer_new_from_data(buffer_to_use, size);
linphone_chat_message_cbs_get_file_transfer_recv(msg->callbacks)(msg, msg->file_transfer_information, lb);
linphone_buffer_unref(lb);
} else {
/* Legacy: call back given by application level */
linphone_core_notify_file_transfer_recv(lc, msg, msg->file_transfer_information, (char *)buffer, size);
linphone_core_notify_file_transfer_recv(lc, msg, msg->file_transfer_information, (const char *)buffer_to_use, size);
}
}
ms_free(decrypted_buffer);
return;
}
@ -446,11 +449,25 @@ static void linphone_chat_process_response_from_get_file(void *data, const belle
int code = belle_http_response_get_status_code(event->response);
if (code == 200) {
LinphoneCore *lc = msg->chat_room->lc;
if (msg->file_transfer_filepath == NULL) {
/* if the file was encrypted, finish the decryption and free context */
if (linphone_content_get_key(msg->file_transfer_information) != NULL) {
lime_decryptFile(linphone_content_get_cryptoContext_address(msg->file_transfer_information), NULL, 0, NULL, NULL);
int retval = -1;
LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(lc);
if (imee) {
LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee);
if (msg->file_transfer_filepath == NULL) {
LinphoneImEncryptionEngineDownloadingFileBufferCb cb_process_downloading_file_buffer = linphone_im_encryption_engine_cbs_get_process_downloading_file_buffer(imee_cbs);
if (cb_process_downloading_file_buffer) {
retval = cb_process_downloading_file_buffer(lc, msg, NULL, 0, NULL);
}
} else {
LinphoneImEncryptionEngineDownloadingFileCb cb_process_downloading_file = linphone_im_encryption_engine_cbs_get_process_downloading_file(imee_cbs);
if (cb_process_downloading_file) {
retval = cb_process_downloading_file(lc, msg, msg->file_transfer_filepath);
}
}
}
if (msg->file_transfer_filepath == NULL) {
if (linphone_chat_message_cbs_get_file_transfer_recv(msg->callbacks)) {
LinphoneBuffer *lb = linphone_buffer_new();
linphone_chat_message_cbs_get_file_transfer_recv(msg->callbacks)(msg, msg->file_transfer_information, lb);
@ -459,28 +476,15 @@ static void linphone_chat_process_response_from_get_file(void *data, const belle
linphone_core_notify_file_transfer_recv(lc, msg, msg->file_transfer_information, NULL, 0);
}
} else {
if (linphone_content_get_key(msg->file_transfer_information) != NULL) {
bctbx_vfs_t *vfs = bctbx_vfs_get_default();
bctbx_vfs_file_t *decrypted_file;
bctbx_vfs_file_t *encrypted_file = bctbx_file_open(vfs, msg->file_transfer_filepath, "r");
size_t encrypted_file_size = (size_t)bctbx_file_size(encrypted_file);
char *encrypted_content = bctbx_malloc(encrypted_file_size);
char *decrypted_content = bctbx_malloc(encrypted_file_size);
bctbx_file_read(encrypted_file, encrypted_content, encrypted_file_size, 0);
bctbx_file_close(encrypted_file);
lime_decryptFile(linphone_content_get_cryptoContext_address(msg->file_transfer_information),
(unsigned char *)linphone_content_get_key(msg->file_transfer_information),
encrypted_file_size, decrypted_content, encrypted_content);
lime_decryptFile(linphone_content_get_cryptoContext_address(msg->file_transfer_information), NULL, 0, NULL, NULL);
decrypted_file = bctbx_file_open(vfs, msg->file_transfer_filepath, "w");
bctbx_file_write(decrypted_file, decrypted_content, encrypted_file_size, 0);
bctbx_file_close(decrypted_file);
bctbx_free(encrypted_content);
bctbx_free(decrypted_content);
}
linphone_core_notify_file_transfer_recv(lc, msg, msg->file_transfer_information, NULL, 0);
}
linphone_chat_message_set_state(msg, LinphoneChatMessageStateFileTransferDone);
if (retval <= 0) {
linphone_chat_message_set_state(msg, LinphoneChatMessageStateFileTransferDone);
} else {
ms_warning("File transfer decrypt failed with code %d", code);
linphone_chat_message_set_state(msg, LinphoneChatMessageStateFileTransferError);
}
} else if (code >= 400 && code < 500) {
ms_warning("File transfer failed with code %d", code);
linphone_chat_message_set_state(msg, LinphoneChatMessageStateFileTransferError);

View file

@ -23,6 +23,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
struct _LinphoneImEncryptionEngineCbs {
void *user_data;
LinphoneImEncryptionEngineIncomingMessageCb process_incoming_message;
LinphoneImEncryptionEngineDownloadingFileBufferCb process_downlading_file_buffer;
LinphoneImEncryptionEngineDownloadingFileCb process_downloading_file;
LinphoneImEncryptionEngineOutgoingMessageCb process_outgoing_message;
};
@ -85,4 +87,20 @@ LinphoneImEncryptionEngineOutgoingMessageCb linphone_im_encryption_engine_cbs_ge
void linphone_im_encryption_engine_cbs_set_process_outgoing_message(LinphoneImEncryptionEngineCbs *cbs, LinphoneImEncryptionEngineOutgoingMessageCb cb) {
cbs->process_outgoing_message = cb;
}
LinphoneImEncryptionEngineDownloadingFileBufferCb linphone_im_encryption_engine_cbs_get_process_downloading_file_buffer(LinphoneImEncryptionEngineCbs *cbs) {
return cbs->process_downlading_file_buffer;
}
void linphone_im_encryption_engine_cbs_set_process_downloading_file_buffer(LinphoneImEncryptionEngineCbs *cbs, LinphoneImEncryptionEngineDownloadingFileBufferCb cb) {
cbs->process_downlading_file_buffer = cb;
}
LinphoneImEncryptionEngineDownloadingFileCb linphone_im_encryption_engine_cbs_get_process_downloading_file(LinphoneImEncryptionEngineCbs *cbs) {
return cbs->process_downloading_file;
}
void linphone_im_encryption_engine_cbs_set_process_downloading_file(LinphoneImEncryptionEngineCbs *cbs, LinphoneImEncryptionEngineDownloadingFileCb cb) {
cbs->process_downloading_file = cb;
}

View file

@ -30,6 +30,10 @@ typedef int (*LinphoneImEncryptionEngineIncomingMessageCb)(LinphoneCore* lc, bel
typedef int (*LinphoneImEncryptionEngineOutgoingMessageCb)(LinphoneCore* lc, belle_sip_request_t* req, const char *peer_uri, const char* content_type, const char* body, char** crypted_body, size_t* content_length);
typedef int (*LinphoneImEncryptionEngineDownloadingFileBufferCb)(LinphoneCore *lc, LinphoneChatMessage *msg, const char *buffer, size_t size, char **decrypted_buffer);
typedef int (*LinphoneImEncryptionEngineDownloadingFileCb)(LinphoneCore *lc, LinphoneChatMessage *msg, const char *path);
typedef struct _LinphoneImEncryptionEngineCbs LinphoneImEncryptionEngineCbs;
typedef struct _LinphoneImEncryptionEngine LinphoneImEncryptionEngine;
@ -60,4 +64,12 @@ LINPHONE_PUBLIC LinphoneImEncryptionEngineOutgoingMessageCb linphone_im_encrypti
LINPHONE_PUBLIC void linphone_im_encryption_engine_cbs_set_process_outgoing_message(LinphoneImEncryptionEngineCbs *cbs, LinphoneImEncryptionEngineOutgoingMessageCb cb);
LINPHONE_PUBLIC LinphoneImEncryptionEngineDownloadingFileBufferCb linphone_im_encryption_engine_cbs_get_process_downloading_file_buffer(LinphoneImEncryptionEngineCbs *cbs);
LINPHONE_PUBLIC void linphone_im_encryption_engine_cbs_set_process_downloading_file_buffer(LinphoneImEncryptionEngineCbs *cbs, LinphoneImEncryptionEngineDownloadingFileBufferCb cb);
LINPHONE_PUBLIC LinphoneImEncryptionEngineDownloadingFileCb linphone_im_encryption_engine_cbs_get_process_downloading_file(LinphoneImEncryptionEngineCbs *cbs);
LINPHONE_PUBLIC void linphone_im_encryption_engine_cbs_set_process_downloading_file(LinphoneImEncryptionEngineCbs *cbs, LinphoneImEncryptionEngineDownloadingFileCb cb);
#endif /* IM_ENCRYPTION_ENGINE_H */

View file

@ -23,6 +23,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#endif
#ifdef HAVE_LIME
#include "private.h"
#include "bctoolbox/crypto.h"
/**
@ -928,6 +929,43 @@ int lime_im_encryption_engine_process_outgoing_message_cb(LinphoneCore* lc, bell
return errcode;
}
int lime_im_encryption_engine_process_downloading_file_buffer_cb(LinphoneCore *lc, LinphoneChatMessage *msg, const char *buffer, size_t size, char **decrypted_buffer) {
if (linphone_content_get_key(msg->file_transfer_information) == NULL) return -1;
if (buffer == NULL || size == 0) {
return lime_decryptFile(linphone_content_get_cryptoContext_address(msg->file_transfer_information), NULL, 0, NULL, NULL);
}
return lime_decryptFile(linphone_content_get_cryptoContext_address(msg->file_transfer_information),
(unsigned char *)linphone_content_get_key(msg->file_transfer_information), size, *decrypted_buffer,
(char *)buffer);
}
int lime_im_encryption_engine_process_downloading_file_cb(LinphoneCore *lc, LinphoneChatMessage *msg, const char *path) {
if (linphone_content_get_key(msg->file_transfer_information) == NULL) {
return -1;
} else {
bctbx_vfs_t *vfs = bctbx_vfs_get_default();
bctbx_vfs_file_t *decrypted_file;
bctbx_vfs_file_t *encrypted_file = bctbx_file_open(vfs, msg->file_transfer_filepath, "r");
size_t encrypted_file_size = (size_t)bctbx_file_size(encrypted_file);
char *encrypted_content = bctbx_malloc(encrypted_file_size);
char *decrypted_content = bctbx_malloc(encrypted_file_size);
bctbx_file_read(encrypted_file, encrypted_content, encrypted_file_size, 0);
bctbx_file_close(encrypted_file);
lime_decryptFile(linphone_content_get_cryptoContext_address(msg->file_transfer_information),
(unsigned char *)linphone_content_get_key(msg->file_transfer_information),
encrypted_file_size, decrypted_content, encrypted_content);
lime_decryptFile(linphone_content_get_cryptoContext_address(msg->file_transfer_information), NULL, 0, NULL, NULL);
decrypted_file = bctbx_file_open(vfs, msg->file_transfer_filepath, "w");
bctbx_file_write(decrypted_file, decrypted_content, encrypted_file_size, 0);
bctbx_file_close(decrypted_file);
bctbx_free(encrypted_content);
bctbx_free(decrypted_content);
return 0;
}
}
#else /* HAVE_LIME */
bool_t lime_is_available() { return FALSE; }
@ -958,6 +996,12 @@ int lime_im_encryption_engine_process_incoming_message_cb(LinphoneCore* lc, bell
int lime_im_encryption_engine_process_outgoing_message_cb(LinphoneCore* lc, belle_sip_request_t* req, const char *peer_uri, const char* content_type, const char* body, char** crypted_body, size_t* content_length) {
return 500;
}
int lime_im_encryption_engine_process_downloading_file_buffer_cb(LinphoneCore *lc, LinphoneChatMessage *msg, const char *buffer, size_t size, char **decrypted_buffer) {
return 500;
}
int lime_im_encryption_engine_process_downloading_file_cb(LinphoneCore *lc, LinphoneChatMessage *msg, const char *path) {
return 500;
}
#endif /* HAVE_LIME */
char *lime_error_code_to_string(int errorCode) {

View file

@ -209,4 +209,8 @@ int lime_im_encryption_engine_process_incoming_message_cb(LinphoneCore* lc, bell
int lime_im_encryption_engine_process_outgoing_message_cb(LinphoneCore* lc, belle_sip_request_t* req, const char *peer_uri, const char* content_type, const char* body, char** crypted_body, size_t* content_length);
int lime_im_encryption_engine_process_downloading_file_buffer_cb(LinphoneCore *lc, LinphoneChatMessage *msg, const char *buffer, size_t size, char **decrypted_buffer);
int lime_im_encryption_engine_process_downloading_file_cb(LinphoneCore *lc, LinphoneChatMessage *msg, const char *path);
#endif /* LIME_H */

View file

@ -1956,6 +1956,8 @@ void linphone_core_enable_lime(LinphoneCore *lc, LinphoneLimeState val){
LinphoneImEncryptionEngineCbs *cbs = linphone_im_encryption_engine_get_callbacks(imee);
linphone_im_encryption_engine_cbs_set_process_incoming_message(cbs, lime_im_encryption_engine_process_incoming_message_cb);
linphone_im_encryption_engine_cbs_set_process_outgoing_message(cbs, lime_im_encryption_engine_process_outgoing_message_cb);
linphone_im_encryption_engine_cbs_set_process_downloading_file_buffer(cbs, lime_im_encryption_engine_process_downloading_file_buffer_cb);
linphone_im_encryption_engine_cbs_set_process_downloading_file(cbs, lime_im_encryption_engine_process_downloading_file_cb);
lc->im_encryption_engine = imee;
} else {
if (lc->im_encryption_engine) {

View file

@ -433,7 +433,6 @@ LINPHONE_PUBLIC const char* linphone_privacy_to_string(LinphonePrivacy privacy);
#include "nat_policy.h"
#include "xmlrpc.h"
#include "conference.h"
#include "im_encryption_engine.h"
#else
#include "linphone/buffer.h"
#include "linphone/call_log.h"
@ -444,7 +443,6 @@ LINPHONE_PUBLIC const char* linphone_privacy_to_string(LinphonePrivacy privacy);
#include "linphone/nat_policy.h"
#include "linphone/xmlrpc.h"
#include "linphone/conference.h"
#include "linphone/im_encryption_engine.h"
#endif
LINPHONE_PUBLIC LinphoneAddress * linphone_address_new(const char *addr);
@ -4731,6 +4729,12 @@ LINPHONE_PUBLIC const char *linphone_core_get_tls_cert_path(const LinphoneCore *
*/
LINPHONE_PUBLIC const char *linphone_core_get_tls_key_path(const LinphoneCore *lc);
#ifdef IN_LINPHONE
#include "im_encryption_engine.h"
#else
#include "linphone/im_encryption_engine.h"
#endif
LINPHONE_PUBLIC void linphone_core_set_im_encryption_engine(LinphoneCore *lc, LinphoneImEncryptionEngine *imee);
LINPHONE_PUBLIC LinphoneImEncryptionEngine * linphone_core_get_im_encryption_engine(const LinphoneCore *lc);

View file

@ -864,6 +864,8 @@ void lime_transfer_message_base(bool_t encrypt_file,bool_t download_file_from_st
LinphoneChatMessageCbs *cbs;
char *pauline_id, *marie_id;
char *filepath;
char *send_filepath = bc_tester_res("images/nowebcamCIF.jpg");
char *receive_filepath = bc_tester_file("receive_file.dump");
marie = linphone_core_manager_new( "marie_rc");
pauline = linphone_core_manager_new( "pauline_tcp_rc");
@ -932,12 +934,15 @@ void lime_transfer_message_base(bool_t encrypt_file,bool_t download_file_from_st
BC_ASSERT_PTR_NULL(linphone_content_get_key(content));
linphone_chat_message_download_file(recv_msg);
BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneFileTransferDownloadSuccessful,1));
compare_files(send_filepath, receive_filepath);
}
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,2, int, "%d"); // file transfer
BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageDelivered,1, int, "%d");
BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneFileTransferDownloadSuccessful,1, int, "%d");
end:
ms_free(send_filepath);
bc_free(receive_filepath);
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
}