diff --git a/coreapi/chat_file_transfer.c b/coreapi/chat_file_transfer.c index 6669257d4..340d6e9d9 100644 --- a/coreapi/chat_file_transfer.c +++ b/coreapi/chat_file_transfer.c @@ -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); diff --git a/coreapi/im_encryption_engine.c b/coreapi/im_encryption_engine.c index b7b43b676..f7cdbbf79 100644 --- a/coreapi/im_encryption_engine.c +++ b/coreapi/im_encryption_engine.c @@ -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; } \ No newline at end of file diff --git a/coreapi/im_encryption_engine.h b/coreapi/im_encryption_engine.h index a5742d721..095be933c 100644 --- a/coreapi/im_encryption_engine.h +++ b/coreapi/im_encryption_engine.h @@ -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 */ \ No newline at end of file diff --git a/coreapi/lime.c b/coreapi/lime.c index fd246198e..78c6a1793 100644 --- a/coreapi/lime.c +++ b/coreapi/lime.c @@ -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) { diff --git a/coreapi/lime.h b/coreapi/lime.h index 717f57064..46d6d96bc 100644 --- a/coreapi/lime.h +++ b/coreapi/lime.h @@ -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 */ diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 3b43bea09..e3fee2bda 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -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) { diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index d51d25cf8..64f2ada6f 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -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); diff --git a/tester/message_tester.c b/tester/message_tester.c index f326bc893..70604d337 100644 --- a/tester/message_tester.c +++ b/tester/message_tester.c @@ -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); }