diff --git a/coreapi/bellesip_sal/sal_op_message.c b/coreapi/bellesip_sal/sal_op_message.c index ccead1c76..48243a548 100644 --- a/coreapi/bellesip_sal/sal_op_message.c +++ b/coreapi/bellesip_sal/sal_op_message.c @@ -100,7 +100,7 @@ void sal_process_incoming_message(SalOp *op,const belle_sip_request_event_t *eve bool_t cipher_xml=FALSE; bool_t rcs_filetransfer=FALSE; uint8_t *decryptedMessage = NULL; - LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); + LinphoneCore *lc = (LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); int retval = -1; from_header=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_from_t); @@ -206,7 +206,9 @@ int sal_message_send(SalOp *op, const char *from, const char *to, const char* co time_t curtime = ms_time(NULL); uint8_t *multipartEncryptedMessage = NULL; const char *body; - int retval; + int retval = -1; + LinphoneCore *lc = (LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); + LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(lc); if (op->dialog){ /*for SIP MESSAGE that are sent in call's dialog*/ @@ -228,59 +230,19 @@ int sal_message_send(SalOp *op, const char *from, const char *to, const char* co } } - /* shall we try to encrypt the message?*/ - if ((strcmp(content_type, "xml/cipher") == 0) || ((strcmp(content_type, "application/cipher.vnd.gsma.rcs-ft-http+xml") == 0))) { - /* access the zrtp cache to get keys needed to cipher the message */ - LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); - FILE *CACHEFD = fopen(lc->zrtp_secrets_cache, "rb+"); - if (CACHEFD == NULL) { - ms_warning("Unable to access ZRTP ZID cache to encrypt message"); - /*probably not a good idea to do this:*/ - sal_error_info_set(&op->error_info, SalReasonNotAcceptable, 488, "Unable to encrypt IM", NULL); - op->base.root->callbacks.text_delivery_update(op,SalTextDeliveryFailed); - return -1; - } else { - size_t cacheSize; - char *cacheString; - xmlDocPtr cacheXml; - int retval; - - cacheString=ms_load_file_content(CACHEFD, &cacheSize); - if (!cacheString){ - ms_warning("Unable to load content of ZRTP ZID cache to encrypt message"); - return -1; - } - cacheString[cacheSize] = '\0'; - cacheSize += 1; - fclose(CACHEFD); - cacheXml = xmlParseDoc((xmlChar*)cacheString); - ms_free(cacheString); - retval = lime_createMultipartMessage(cacheXml, (uint8_t *)msg, (uint8_t *)peer_uri, &multipartEncryptedMessage); - if (retval != 0) { - ms_warning("Unable to encrypt message for %s : %s - op [%p]", peer_uri, lime_error_code_to_string(retval), op); - xmlFreeDoc(cacheXml); - free(multipartEncryptedMessage); - /*probably not a good idea to do this:*/ - sal_error_info_set(&op->error_info, SalReasonNotAcceptable, 488, "Unable to encrypt IM", NULL); - op->base.root->callbacks.text_delivery_update(op,SalTextDeliveryFailed); - return -1; - } else { - /* dump updated cache to a string */ - xmlChar *xmlStringOutput; - int xmlStringLength; - xmlDocDumpFormatMemoryEnc(cacheXml, &xmlStringOutput, &xmlStringLength, "UTF-8", 0); - /* write it to the cache file */ - CACHEFD = fopen(lc->zrtp_secrets_cache, "wb+"); - if (fwrite(xmlStringOutput, 1, xmlStringLength, CACHEFD)<=0){ - ms_warning("Unable to write zid cache"); - } - xmlFree(xmlStringOutput); - fclose(CACHEFD); - content_length = strlen((const char *)multipartEncryptedMessage); - } - xmlFreeDoc(cacheXml); + if (imee) { + LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee); + LinphoneImEncryptionEngineOutgoingMessageCb cb_process_outgoing_message = linphone_im_encryption_engine_cbs_get_process_outgoing_message(imee_cbs); + if (cb_process_outgoing_message) { + retval = cb_process_outgoing_message(lc, peer_uri, content_type, msg, (char **)&multipartEncryptedMessage, &content_length); } } + if (retval > 0) { + /*probably not a good idea to do this:*/ + sal_error_info_set(&op->error_info, SalReasonNotAcceptable, retval, "Unable to encrypt IM", NULL); + op->base.root->callbacks.text_delivery_update(op, SalTextDeliveryFailed); + return -1; + } snprintf(content_type_raw,sizeof(content_type_raw),BELLE_SIP_CONTENT_TYPE ": %s",content_type); belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_content_type_parse(content_type_raw))); diff --git a/coreapi/im_encryption_engine.c b/coreapi/im_encryption_engine.c index cf6a34530..95b019eac 100644 --- a/coreapi/im_encryption_engine.c +++ b/coreapi/im_encryption_engine.c @@ -23,6 +23,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. struct _LinphoneImEncryptionEngineCbs { void *user_data; LinphoneImEncryptionEngineIncomingMessageCb process_incoming_message; + LinphoneImEncryptionEngineOutgoingMessageCb process_outgoing_message; }; struct _LinphoneImEncryptionEngine { @@ -68,4 +69,12 @@ LinphoneImEncryptionEngineIncomingMessageCb linphone_im_encryption_engine_cbs_ge void linphone_im_encryption_engine_cbs_set_process_incoming_message(LinphoneImEncryptionEngineCbs *cbs, LinphoneImEncryptionEngineIncomingMessageCb cb) { cbs->process_incoming_message = cb; +} + +LinphoneImEncryptionEngineOutgoingMessageCb linphone_im_encryption_engine_cbs_get_process_outgoing_message(LinphoneImEncryptionEngineCbs *cbs) { + return cbs->process_outgoing_message; +} + +void linphone_im_encryption_engine_cbs_set_process_outgoing_message(LinphoneImEncryptionEngineCbs *cbs, LinphoneImEncryptionEngineOutgoingMessageCb cb) { + cbs->process_outgoing_message = cb; } \ No newline at end of file diff --git a/coreapi/im_encryption_engine.h b/coreapi/im_encryption_engine.h index 7ab571dbe..17ac20ea3 100644 --- a/coreapi/im_encryption_engine.h +++ b/coreapi/im_encryption_engine.h @@ -28,6 +28,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. typedef int (*LinphoneImEncryptionEngineIncomingMessageCb)(LinphoneCore* lc, const char* content_type, const char* content_subtype, const char* body, char** decrypted_body); +typedef int (*LinphoneImEncryptionEngineOutgoingMessageCb)(LinphoneCore* lc, const char *peer_uri, const char* content_type, const char* body, char** crypted_body, size_t* content_length); + typedef struct _LinphoneImEncryptionEngineCbs LinphoneImEncryptionEngineCbs; typedef struct _LinphoneImEncryptionEngine LinphoneImEncryptionEngine; @@ -50,4 +52,8 @@ LINPHONE_PUBLIC LinphoneImEncryptionEngineIncomingMessageCb linphone_im_encrypti LINPHONE_PUBLIC void linphone_im_encryption_engine_cbs_set_process_incoming_message(LinphoneImEncryptionEngineCbs *cbs, LinphoneImEncryptionEngineIncomingMessageCb cb); +LINPHONE_PUBLIC LinphoneImEncryptionEngineOutgoingMessageCb linphone_im_encryption_engine_cbs_get_process_outgoing_message(LinphoneImEncryptionEngineCbs *cbs); + +LINPHONE_PUBLIC void linphone_im_encryption_engine_cbs_set_process_outgoing_message(LinphoneImEncryptionEngineCbs *cbs, LinphoneImEncryptionEngineOutgoingMessageCb cb); + #endif /* IM_ENCRYPTION_ENGINE_H */ \ No newline at end of file diff --git a/coreapi/lime.c b/coreapi/lime.c index 833161818..845f2de98 100644 --- a/coreapi/lime.c +++ b/coreapi/lime.c @@ -851,7 +851,7 @@ int lime_im_encryption_engine_process_incoming_message_cb(LinphoneCore* lc, cons retval = lime_decryptMultipartMessage(cacheXml, (uint8_t *)body, (uint8_t **)decrypted_body); if (retval != 0) { ms_warning("Unable to decrypt message, reason : %s", lime_error_code_to_string(retval)); - free(decrypted_body); + if (*decrypted_body) free(*decrypted_body); xmlFreeDoc(cacheXml); errcode = 488; return errcode; @@ -875,6 +875,58 @@ int lime_im_encryption_engine_process_incoming_message_cb(LinphoneCore* lc, cons return errcode; } +int lime_im_encryption_engine_process_outgoing_message_cb(LinphoneCore* lc, const char *peer_uri, const char* content_type, const char* body, char** crypted_body, size_t* content_length) { + int errcode = -1; + /* shall we try to encrypt the message?*/ + if ((strcmp(content_type, "xml/cipher") == 0) || ((strcmp(content_type, "application/cipher.vnd.gsma.rcs-ft-http+xml") == 0))) { + /* access the zrtp cache to get keys needed to cipher the message */ + const char *zrtp_secrets_cache = linphone_core_get_zrtp_secrets_file(lc); + FILE *CACHEFD = fopen(zrtp_secrets_cache, "rb+"); + errcode = 0; + if (CACHEFD == NULL) { + ms_warning("Unable to access ZRTP ZID cache to encrypt message"); + errcode = 488; + } else { + size_t cacheSize; + char *cacheString; + xmlDocPtr cacheXml; + int retval; + + cacheString=ms_load_file_content(CACHEFD, &cacheSize); + if (!cacheString){ + ms_warning("Unable to load content of ZRTP ZID cache to encrypt message"); + errcode = 500; + return errcode; + } + cacheString[cacheSize] = '\0'; + cacheSize += 1; + fclose(CACHEFD); + cacheXml = xmlParseDoc((xmlChar*)cacheString); + ms_free(cacheString); + retval = lime_createMultipartMessage(cacheXml, (uint8_t *)body, (uint8_t *)peer_uri, (uint8_t **)crypted_body); + if (retval != 0) { + ms_warning("Unable to encrypt message for %s : %s", peer_uri, lime_error_code_to_string(retval)); + if (*crypted_body) free(*crypted_body); + errcode = 488; + } else { + /* dump updated cache to a string */ + xmlChar *xmlStringOutput; + int xmlStringLength; + xmlDocDumpFormatMemoryEnc(cacheXml, &xmlStringOutput, &xmlStringLength, "UTF-8", 0); + /* write it to the cache file */ + CACHEFD = fopen(zrtp_secrets_cache, "wb+"); + if (fwrite(xmlStringOutput, 1, xmlStringLength, CACHEFD)<=0){ + ms_warning("Unable to write zid cache"); + } + xmlFree(xmlStringOutput); + fclose(CACHEFD); + *content_length = strlen((const char *)*crypted_body); + } + xmlFreeDoc(cacheXml); + } + } + return errcode; +} #else /* HAVE_LIME */ @@ -903,6 +955,9 @@ int lime_decryptMessage(limeKey_t *key, uint8_t *encryptedMessage, uint32_t mess int lime_im_encryption_engine_process_incoming_message_cb(LinphoneCore* lc, const char* content_type, const char* content_subtype, const char* body, char** decrypted_body) { return 500; } +int lime_im_encryption_engine_process_outgoing_message_cb(LinphoneCore* lc, const char *peer_uri, const char* content_type, const char* body, char** crypted_body, size_t* content_length) { + return 500; +} #endif /* HAVE_LIME */ char *lime_error_code_to_string(int errorCode) { diff --git a/coreapi/lime.h b/coreapi/lime.h index f33622812..db2ef6994 100644 --- a/coreapi/lime.h +++ b/coreapi/lime.h @@ -207,4 +207,6 @@ LINPHONE_PUBLIC bool_t lime_is_available(void); int lime_im_encryption_engine_process_incoming_message_cb(LinphoneCore* lc, const char* content_type, const char* content_subtype, const char* body, char** decrypted_body); +int lime_im_encryption_engine_process_outgoing_message_cb(LinphoneCore* lc, const char *peer_uri, const char* content_type, const char* body, char** crypted_body, size_t* content_length); + #endif /* LIME_H */ diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 6bd808c56..3b43bea09 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -1955,6 +1955,7 @@ void linphone_core_enable_lime(LinphoneCore *lc, LinphoneLimeState val){ LinphoneImEncryptionEngine *imee = linphone_im_encryption_engine_new(); 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); lc->im_encryption_engine = imee; } else { if (lc->im_encryption_engine) {