Reworked im encryption engine to be at linphone level instead of sal level

This commit is contained in:
Sylvain Berfini 2016-11-10 12:02:56 +01:00
parent e8258de05b
commit 3214b4371a
9 changed files with 241 additions and 204 deletions

View file

@ -59,16 +59,6 @@ static void process_response_event(void *op_base, const belle_sip_response_event
op->base.root->callbacks.text_delivery_update(op,status);
}
static bool_t is_rcs_filetransfer(belle_sip_header_content_type_t* content_type) {
return (strcmp("application",belle_sip_header_content_type_get_type(content_type))==0)
&& ((strcmp("vnd.gsma.rcs-ft-http+xml",belle_sip_header_content_type_get_subtype(content_type))==0) || (strcmp("cipher.vnd.gsma.rcs-ft-http+xml",belle_sip_header_content_type_get_subtype(content_type))==0));
}
static bool_t is_plain_text(belle_sip_header_content_type_t* content_type) {
return strcmp("text",belle_sip_header_content_type_get_type(content_type))==0
&& strcmp("plain",belle_sip_header_content_type_get_subtype(content_type))==0;
}
static bool_t is_external_body(belle_sip_header_content_type_t* content_type) {
return strcmp("message",belle_sip_header_content_type_get_type(content_type))==0
&& strcmp("external-body",belle_sip_header_content_type_get_subtype(content_type))==0;
@ -94,40 +84,29 @@ void sal_process_incoming_message(SalOp *op,const belle_sip_request_event_t *eve
belle_sip_header_cseq_t* cseq = belle_sip_message_get_header_by_type(req,belle_sip_header_cseq_t);
belle_sip_header_date_t *date=belle_sip_message_get_header_by_type(req,belle_sip_header_date_t);
char* from;
bool_t plain_text=FALSE;
bool_t external_body=FALSE;
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));
int retval = -1;
from_header=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_from_t);
content_type=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_content_type_t);
if (content_type) {
LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(lc);
if (imee) {
LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee);
LinphoneImEncryptionEngineIncomingMessageCb cb_process_incoming_message = linphone_im_encryption_engine_cbs_get_process_incoming_message(imee_cbs);
if (cb_process_incoming_message) {
retval = cb_process_incoming_message(lc, req, belle_sip_header_content_type_get_type(content_type), belle_sip_header_content_type_get_subtype(content_type),
belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)), (char **)&decryptedMessage);
}
}
cipher_xml = retval >= 0;
if (retval > 0) {
errcode = retval;
goto error;
}
external_body=is_external_body(content_type);
plain_text=is_plain_text(content_type);
rcs_filetransfer = is_rcs_filetransfer(content_type);
if (external_body || plain_text || rcs_filetransfer || decryptedMessage!=NULL) {
if (is_im_iscomposing(content_type)) {
SalIsComposing saliscomposing;
address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(from_header))
,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from_header)));
from=belle_sip_object_to_string(BELLE_SIP_OBJECT(address));
saliscomposing.from=from;
saliscomposing.text=belle_sip_message_get_body(BELLE_SIP_MESSAGE(req));
op->base.root->callbacks.is_composing_received(op,&saliscomposing);
resp = belle_sip_response_create_from_request(req,200);
belle_sip_server_transaction_send_response(server_transaction,resp);
belle_sip_object_unref(address);
belle_sip_free(from);
} else {
SalMessage salmsg;
char message_id[256]={0};
external_body=is_external_body(content_type);
if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans);
op->pending_server_trans=server_transaction;
@ -141,16 +120,9 @@ void sal_process_incoming_message(SalOp *op,const belle_sip_request_event_t *eve
,belle_sip_header_cseq_get_seq_number(cseq));
salmsg.from=from;
/* if we just deciphered a message, use the deciphered part(which can be a rcs xml body pointing to the file to retreive from server)*/
if (cipher_xml) {
salmsg.text = (char *)decryptedMessage;
} else { /* message body wasn't ciphered */
salmsg.text=(plain_text||rcs_filetransfer)?belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)):NULL;
}
salmsg.text=(!external_body)?belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)):NULL;
salmsg.url=NULL;
salmsg.content_type = NULL;
if (rcs_filetransfer) { /* if we have a rcs file transfer, set the type, message body (stored in salmsg.text) contains all needed information to retrieve the file */
salmsg.content_type = "application/vnd.gsma.rcs-ft-http+xml";
}
salmsg.content_type = ms_strdup_printf("%s/%s", belle_sip_header_content_type_get_type(content_type), belle_sip_header_content_type_get_subtype(content_type));
if (external_body && belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")) {
size_t url_length=strlen(belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL"));
salmsg.url = ms_strdup(belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")+1); /* skip first "*/
@ -160,28 +132,11 @@ void sal_process_incoming_message(SalOp *op,const belle_sip_request_event_t *eve
salmsg.time=date ? belle_sip_header_date_get_time(date) : time(NULL);
op->base.root->callbacks.text_received(op,&salmsg);
free(decryptedMessage);
belle_sip_object_unref(address);
belle_sip_free(from);
if (salmsg.url) ms_free((char*)salmsg.url);
} else if (is_im_iscomposing(content_type)) {
SalIsComposing saliscomposing;
address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(from_header))
,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from_header)));
from=belle_sip_object_to_string(BELLE_SIP_OBJECT(address));
saliscomposing.from=from;
saliscomposing.text=belle_sip_message_get_body(BELLE_SIP_MESSAGE(req));
op->base.root->callbacks.is_composing_received(op,&saliscomposing);
resp = belle_sip_response_create_from_request(req,200);
belle_sip_server_transaction_send_response(server_transaction,resp);
belle_sip_object_unref(address);
belle_sip_free(from);
}else{
ms_error("Unsupported MESSAGE (content-type not recognized)");
errcode = 415;
goto error;
}
}else {
} else {
ms_error("Unsupported MESSAGE (no Content-Type)");
goto error;
}
@ -203,11 +158,8 @@ int sal_message_send(SalOp *op, const char *from, const char *to, const char* co
char content_type_raw[256];
size_t content_length = msg?strlen(msg):0;
time_t curtime = ms_time(NULL);
uint8_t *multipartEncryptedMessage = NULL;
const char *body;
int retval = -1;
LinphoneCore *lc = (LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(lc);
int retval;
if (op->dialog){
/*for SIP MESSAGE that are sent in call's dialog*/
@ -229,31 +181,16 @@ int sal_message_send(SalOp *op, const char *from, const char *to, const char* co
}
}
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, req, 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)));
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_content_length_create(content_length)));
belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_date_create_from_time(&curtime)));
body = (multipartEncryptedMessage==NULL) ? msg : (char*) multipartEncryptedMessage;
body = msg;
if (body){
/*don't call set_body() with null argument because it resets content type and content length*/
belle_sip_message_set_body(BELLE_SIP_MESSAGE(req), body, content_length);
}
retval = sal_op_send_request(op,req);
free(multipartEncryptedMessage);
return retval;
}

View file

@ -1159,10 +1159,11 @@ static bool_t is_duplicate_msg(LinphoneCore *lc, const char *msg_id){
static void text_received(SalOp *op, const SalMessage *msg){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
if (lc->chat_deny_code==LinphoneReasonNone && is_duplicate_msg(lc,msg->message_id)==FALSE){
linphone_core_message_received(lc,op,msg);
LinphoneReason reason = lc->chat_deny_code;
if (reason == LinphoneReasonNone && is_duplicate_msg(lc, msg->message_id) == FALSE) {
reason = linphone_core_message_received(lc, op, msg);
}
sal_message_reply(op,linphone_reason_to_sal(lc->chat_deny_code));
sal_message_reply(op,linphone_reason_to_sal(reason));
if (!call) sal_op_release(op);
}

View file

@ -27,7 +27,6 @@
#include "lpconfig.h"
#include "belle-sip/belle-sip.h"
#include "ortp/b64.h"
#include "lime.h"
#include <libxml/parser.h>
#include <libxml/tree.h>
@ -265,50 +264,6 @@ LinphoneChatRoom *linphone_core_get_chat_room_from_uri(LinphoneCore *lc, const c
return _linphone_core_get_or_create_chat_room(lc, to);
}
bool_t linphone_chat_room_lime_available(LinphoneChatRoom *cr) {
if (cr) {
switch (linphone_core_lime_enabled(cr->lc)) {
case LinphoneLimeDisabled: return FALSE;
case LinphoneLimeMandatory: return TRUE;
case LinphoneLimePreferred: {
FILE *CACHEFD = NULL;
if (cr->lc->zrtp_secrets_cache != NULL) {
CACHEFD = fopen(cr->lc->zrtp_secrets_cache, "rb+");
if (CACHEFD) {
size_t cacheSize;
xmlDocPtr cacheXml;
char *cacheString=ms_load_file_content(CACHEFD, &cacheSize);
if (!cacheString){
ms_warning("Unable to load content of ZRTP ZID cache to decrypt message");
return FALSE;
}
cacheString[cacheSize] = '\0';
cacheSize += 1;
fclose(CACHEFD);
cacheXml = xmlParseDoc((xmlChar*)cacheString);
ms_free(cacheString);
if (cacheXml) {
bool_t res;
limeURIKeys_t associatedKeys;
/* retrieve keys associated to the peer URI */
associatedKeys.peerURI = (uint8_t *)malloc(strlen(cr->peer)+1);
strcpy((char *)(associatedKeys.peerURI), cr->peer);
associatedKeys.associatedZIDNumber = 0;
associatedKeys.peerKeys = NULL;
res = (lime_getCachedSndKeysByURI(cacheXml, &associatedKeys) == 0 && associatedKeys.associatedZIDNumber != 0);
lime_freeKeys(&associatedKeys);
xmlFreeDoc(cacheXml);
return res;
}
}
}
}
}
}
return FALSE;
}
static void linphone_chat_room_delete_composing_idle_timer(LinphoneChatRoom *cr) {
if (cr->composing_idle_timer) {
if (cr->lc && cr->lc->sal)
@ -366,6 +321,10 @@ void linphone_chat_room_set_user_data(LinphoneChatRoom *cr, void *ud) {
}
void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg) {
int retval = -1;
LinphoneCore *lc = cr->lc;
LinphoneImEncryptionEngine *imee = lc->im_encryption_engine;
/*stubed rtt text*/
if (cr->call && linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(cr->call))) {
uint32_t new_line = 0x2028;
@ -406,6 +365,15 @@ void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage
}
}
}
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, cr, msg);
}
}
if (op == NULL) {
LinphoneProxyConfig *proxy = linphone_core_lookup_known_proxy(cr->lc, cr->peer_url);
if (proxy) {
@ -418,6 +386,13 @@ void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage
lp_config_get_int(cr->lc->config, "sip", "chat_msg_with_contact", 0));
sal_op_set_user_pointer(op, msg); /*if out of call, directly store msg*/
}
if (retval > 0) {
sal_error_info_set((SalErrorInfo *)sal_op_get_error_info(op), SalReasonNotAcceptable, retval, "Unable to encrypt IM", NULL);
linphone_chat_message_update_state(msg, LinphoneChatMessageStateNotDelivered);
linphone_chat_message_unref(msg);
return;
}
if (msg->external_body_url) {
content_type = ms_strdup_printf("message/external-body; access-type=URL; URL=\"%s\"", msg->external_body_url);
@ -425,21 +400,7 @@ void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage
ms_free(content_type);
} else {
char *peer_uri = linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr));
const char *content_type;
if (linphone_chat_room_lime_available(cr)) {
/* ref the msg or it may be destroyed by callback if the encryption failed */
if (msg->content_type && strcmp(msg->content_type, "application/vnd.gsma.rcs-ft-http+xml") == 0) {
/* it's a file transfer, content type shall be set to
application/cipher.vnd.gsma.rcs-ft-http+xml*/
content_type = "application/cipher.vnd.gsma.rcs-ft-http+xml";
} else {
content_type = "xml/cipher";
}
} else {
content_type = msg->content_type;
}
const char *content_type = msg->content_type;
if (content_type == NULL) {
sal_text_send(op, identity, cr->peer, msg->message);
} else {
@ -509,30 +470,68 @@ void linphone_chat_room_message_received(LinphoneChatRoom *cr, LinphoneCore *lc,
linphone_core_notify_is_composing_received(cr->lc, cr);
}
void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessage *sal_msg) {
LinphoneReason linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessage *sal_msg) {
LinphoneChatRoom *cr = NULL;
LinphoneAddress *addr;
LinphoneAddress *to;
LinphoneChatMessage *msg;
LinphoneImEncryptionEngine *imee = lc->im_encryption_engine;
const SalCustomHeader *ch;
LinphoneReason reason = LinphoneReasonNone;
int retval = -1;
addr = linphone_address_new(sal_msg->from);
linphone_address_clean(addr);
cr = linphone_core_get_chat_room(lc, addr);
if (sal_msg->content_type !=
NULL) { /* content_type field is, for now, used only for rcs file transfer but we shall strcmp it with
"application/vnd.gsma.rcs-ft-http+xml" */
msg = linphone_chat_room_create_message(cr, sal_msg->text); /* create a msg with empty body */
msg->content_type = ms_strdup(sal_msg->content_type); /* add the content_type "application/vnd.gsma.rcs-ft-http+xml" */
linphone_chat_message_set_from(msg, cr->peer_url);
to = sal_op_get_to(op) ? linphone_address_new(sal_op_get_to(op)) : linphone_address_new(linphone_core_get_identity(lc));
msg->to = to;
msg->time = sal_msg->time;
msg->state = LinphoneChatMessageStateDelivered;
msg->is_read = FALSE;
msg->dir = LinphoneChatMessageIncoming;
ch = sal_op_get_recv_custom_header(op);
if (ch) {
msg->custom_headers = sal_custom_header_clone(ch);
}
if (sal_msg->url) {
linphone_chat_message_set_external_body_url(msg, sal_msg->url);
}
if (imee) {
LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee);
LinphoneImEncryptionEngineIncomingMessageCb cb_process_incoming_message = linphone_im_encryption_engine_cbs_get_process_incoming_message(imee_cbs);
if (cb_process_incoming_message) {
retval = cb_process_incoming_message(lc, cr, msg);
}
}
if (retval < 0 && strcmp("text/plain", msg->content_type) != 0 && strcmp("message/external-body", msg->content_type) != 0
&& strcmp("application/vnd.gsma.rcs-ft-http+xml", msg->content_type) != 0) {
retval = 415;
ms_error("Unsupported MESSAGE (content-type %s not recognized)", msg->content_type);
}
if (retval > 0) {
reason = linphone_error_code_to_reason(retval);
goto end;
}
if (strcmp("application/vnd.gsma.rcs-ft-http+xml", msg->content_type) == 0) {
xmlChar *file_url = NULL;
xmlDocPtr xmlMessageBody;
xmlNodePtr cur;
msg = linphone_chat_room_create_message(cr, NULL); /* create a msg with empty body */
msg->content_type =
ms_strdup(sal_msg->content_type); /* add the content_type "application/vnd.gsma.rcs-ft-http+xml" */
msg->file_transfer_information = linphone_content_new();
/* content_type field is, for now, used only for rcs file transfer but we shall strcmp it with "application/vnd.gsma.rcs-ft-http+xml" */
/* parse the msg body to get all informations from it */
xmlMessageBody = xmlParseDoc((const xmlChar *)sal_msg->text);
xmlMessageBody = xmlParseDoc((const xmlChar *)msg->message);
msg->file_transfer_information = linphone_content_new();
cur = xmlDocGetRootElement(xmlMessageBody);
if (cur != NULL) {
@ -609,31 +608,8 @@ void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessag
linphone_chat_message_set_external_body_url(msg, (const char *)file_url);
xmlFree(file_url);
} else { /* msg is not rcs file transfer, create it with provided sal_msg->text as ->msg */
msg = linphone_chat_room_create_message(cr, sal_msg->text);
}
linphone_chat_message_set_from(msg, cr->peer_url);
{
LinphoneAddress *to;
to = sal_op_get_to(op) ? linphone_address_new(sal_op_get_to(op))
: linphone_address_new(linphone_core_get_identity(lc));
msg->to = to;
}
msg->time = sal_msg->time;
msg->state = LinphoneChatMessageStateDelivered;
msg->is_read = FALSE;
msg->dir = LinphoneChatMessageIncoming;
ch = sal_op_get_recv_custom_header(op);
if (ch)
msg->custom_headers = sal_custom_header_clone(ch);
if (sal_msg->url) {
linphone_chat_message_set_external_body_url(msg, sal_msg->url);
}
linphone_address_destroy(addr);
msg->storage_id = linphone_chat_message_store(msg);
if (cr->unread_count < 0)
@ -642,7 +618,11 @@ void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessag
cr->unread_count++;
linphone_chat_room_message_received(cr, lc, msg);
end:
linphone_address_destroy(addr);
linphone_chat_message_unref(msg);
return reason;
}
static int linphone_chat_room_remote_refresh_composing_expired(void *data, unsigned int revents) {

View file

@ -26,9 +26,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#define LINPHONE_PUBLIC MS2_PUBLIC
#endif
typedef int (*LinphoneImEncryptionEngineIncomingMessageCb)(LinphoneCore* lc, belle_sip_request_t* req, const char* content_type, const char* content_subtype, const char* body, char** decrypted_body);
typedef int (*LinphoneImEncryptionEngineIncomingMessageCb)(LinphoneCore* lc, LinphoneChatRoom *room, LinphoneChatMessage *msg);
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 (*LinphoneImEncryptionEngineOutgoingMessageCb)(LinphoneCore* lc, LinphoneChatRoom *room, LinphoneChatMessage *msg);
typedef int (*LinphoneImEncryptionEngineDownloadingFileCb)(LinphoneCore *lc, LinphoneChatMessage *msg, const char *buffer, size_t size, char **decrypted_buffer);

View file

@ -812,17 +812,54 @@ int lime_decryptMultipartMessage(xmlDocPtr cacheBuffer, uint8_t *message, uint8_
return 0;
}
static bool_t is_cipher_xml(const char* content_type, const char *content_subtype) {
return (strcmp("xml",content_type)==0
&& strcmp("cipher",content_subtype)==0)
|| (strcmp("application",content_type)==0
&& strcmp("cipher.vnd.gsma.rcs-ft-http+xml",content_subtype)==0);
bool_t linphone_chat_room_lime_available(LinphoneChatRoom *cr) {
if (cr) {
switch (linphone_core_lime_enabled(cr->lc)) {
case LinphoneLimeDisabled: return FALSE;
case LinphoneLimeMandatory: return TRUE;
case LinphoneLimePreferred: {
FILE *CACHEFD = NULL;
if (cr->lc->zrtp_secrets_cache != NULL) {
CACHEFD = fopen(cr->lc->zrtp_secrets_cache, "rb+");
if (CACHEFD) {
size_t cacheSize;
xmlDocPtr cacheXml;
char *cacheString=ms_load_file_content(CACHEFD, &cacheSize);
if (!cacheString){
ms_warning("Unable to load content of ZRTP ZID cache to decrypt message");
return FALSE;
}
cacheString[cacheSize] = '\0';
cacheSize += 1;
fclose(CACHEFD);
cacheXml = xmlParseDoc((xmlChar*)cacheString);
ms_free(cacheString);
if (cacheXml) {
bool_t res;
limeURIKeys_t associatedKeys;
/* retrieve keys associated to the peer URI */
associatedKeys.peerURI = (uint8_t *)malloc(strlen(cr->peer)+1);
strcpy((char *)(associatedKeys.peerURI), cr->peer);
associatedKeys.associatedZIDNumber = 0;
associatedKeys.peerKeys = NULL;
res = (lime_getCachedSndKeysByURI(cacheXml, &associatedKeys) == 0 && associatedKeys.associatedZIDNumber != 0);
lime_freeKeys(&associatedKeys);
xmlFreeDoc(cacheXml);
return res;
}
}
}
}
}
}
return FALSE;
}
int lime_im_encryption_engine_process_incoming_message_cb(LinphoneCore* lc, belle_sip_request_t* req, const char* content_type, const char* content_subtype, const char* body, char** decrypted_body) {
int lime_im_encryption_engine_process_incoming_message_cb(LinphoneCore* lc, LinphoneChatRoom *room, LinphoneChatMessage *msg) {
int errcode = -1;
/* check if we have a xml/cipher message to be decrypted */
if (is_cipher_xml(content_type, content_subtype)) {
if (msg->content_type && (strcmp("xml/cipher", msg->content_type) == 0 || strcmp("application/cipher.vnd.gsma.rcs-ft-http+xml", msg->content_type) == 0)) {
/* access the zrtp cache to get keys needed to decipher the message */
FILE *CACHEFD = NULL;
const char *zrtp_secrets_cache = linphone_core_get_zrtp_secrets_file(lc);
@ -837,6 +874,7 @@ int lime_im_encryption_engine_process_incoming_message_cb(LinphoneCore* lc, bell
char *cacheString;
int retval;
xmlDocPtr cacheXml;
uint8_t *decrypted_body = NULL;
cacheString=ms_load_file_content(CACHEFD, &cacheSize);
if (!cacheString){
@ -849,10 +887,10 @@ int lime_im_encryption_engine_process_incoming_message_cb(LinphoneCore* lc, bell
fclose(CACHEFD);
cacheXml = xmlParseDoc((xmlChar*)cacheString);
ms_free(cacheString);
retval = lime_decryptMultipartMessage(cacheXml, (uint8_t *)body, (uint8_t **)decrypted_body);
retval = lime_decryptMultipartMessage(cacheXml, (uint8_t *)msg->message, &decrypted_body);
if (retval != 0) {
ms_warning("Unable to decrypt message, reason : %s", lime_error_code_to_string(retval));
if (*decrypted_body) free(*decrypted_body);
if (decrypted_body) free(decrypted_body);
xmlFreeDoc(cacheXml);
errcode = 488;
return errcode;
@ -868,6 +906,18 @@ int lime_im_encryption_engine_process_incoming_message_cb(LinphoneCore* lc, bell
}
xmlFree(xmlStringOutput);
fclose(CACHEFD);
if (msg->message) {
ms_free(msg->message);
}
msg->message = (char *)decrypted_body;
if (strcmp("application/cipher.vnd.gsma.rcs-ft-http+xml", msg->content_type) == 0) {
ms_free(msg->content_type);
msg->content_type = ms_strdup("application/vnd.gsma.rcs-ft-http+xml");
} else {
ms_free(msg->content_type);
msg->content_type = ms_strdup("text/plain");
}
}
xmlFreeDoc(cacheXml);
@ -876,10 +926,21 @@ int lime_im_encryption_engine_process_incoming_message_cb(LinphoneCore* lc, bell
return errcode;
}
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_outgoing_message_cb(LinphoneCore* lc, LinphoneChatRoom *room, LinphoneChatMessage *msg) {
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))) {
char *content_type = NULL;
if (linphone_chat_room_lime_available(room)) {
if (msg->content_type && strcmp(msg->content_type, "application/vnd.gsma.rcs-ft-http+xml") == 0) {
/* it's a file transfer, content type shall be set to
application/cipher.vnd.gsma.rcs-ft-http+xml*/
content_type = "application/cipher.vnd.gsma.rcs-ft-http+xml";
} else {
content_type = "xml/cipher";
}
msg->content_type = ms_strdup(content_type);
/* 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+");
@ -892,6 +953,8 @@ int lime_im_encryption_engine_process_outgoing_message_cb(LinphoneCore* lc, bell
char *cacheString;
xmlDocPtr cacheXml;
int retval;
uint8_t *crypted_body = NULL;
char *peer = linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(room));
cacheString=ms_load_file_content(CACHEFD, &cacheSize);
if (!cacheString){
@ -904,10 +967,10 @@ int lime_im_encryption_engine_process_outgoing_message_cb(LinphoneCore* lc, bell
fclose(CACHEFD);
cacheXml = xmlParseDoc((xmlChar*)cacheString);
ms_free(cacheString);
retval = lime_createMultipartMessage(cacheXml, (uint8_t *)body, (uint8_t *)peer_uri, (uint8_t **)crypted_body);
retval = lime_createMultipartMessage(cacheXml, (uint8_t *)msg->message, (uint8_t *)peer, &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);
ms_warning("Unable to encrypt message for %s : %s", peer, lime_error_code_to_string(retval));
if (crypted_body) free(crypted_body);
errcode = 488;
} else {
/* dump updated cache to a string */
@ -921,8 +984,12 @@ int lime_im_encryption_engine_process_outgoing_message_cb(LinphoneCore* lc, bell
}
xmlFree(xmlStringOutput);
fclose(CACHEFD);
*content_length = strlen((const char *)*crypted_body);
if (msg->message) {
ms_free(msg->message);
}
msg->message = (char *)crypted_body;
}
ms_free(peer);
xmlFreeDoc(cacheXml);
}
}
@ -965,10 +1032,13 @@ int lime_getCachedRcvKeyByZid(xmlDocPtr cacheBuffer, limeKey_t *associatedKey) {
int lime_decryptMessage(limeKey_t *key, uint8_t *encryptedMessage, uint32_t messageLength, uint8_t selfZID[12], uint8_t *plainMessage) {
return LIME_NOT_ENABLED;
}
int lime_im_encryption_engine_process_incoming_message_cb(LinphoneCore* lc, belle_sip_request_t* req, const char* content_type, const char* content_subtype, const char* body, char** decrypted_body) {
bool_t linphone_chat_room_lime_available(LinphoneChatRoom *cr) {
return FALSE;
}
int lime_im_encryption_engine_process_incoming_message_cb(LinphoneCore* lc, LinphoneChatRoom *room, LinphoneChatMessage *msg) {
return 500;
}
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_outgoing_message_cb(LinphoneCore* lc, LinphoneChatRoom *room, LinphoneChatMessage *msg) {
return 500;
}
int lime_im_encryption_engine_process_downloading_file_cb(LinphoneCore *lc, LinphoneChatMessage *msg, const char *buffer, size_t size, char **decrypted_buffer) {

View file

@ -205,9 +205,9 @@ LINPHONE_PUBLIC char *lime_error_code_to_string(int errorCode);
*/
LINPHONE_PUBLIC bool_t lime_is_available(void);
int lime_im_encryption_engine_process_incoming_message_cb(LinphoneCore* lc, belle_sip_request_t* req, const char* content_type, const char* content_subtype, const char* body, char** decrypted_body);
int lime_im_encryption_engine_process_incoming_message_cb(LinphoneCore* lc, LinphoneChatRoom *room, LinphoneChatMessage *msg);
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_outgoing_message_cb(LinphoneCore* lc, LinphoneChatRoom *room, LinphoneChatMessage *msg);
int lime_im_encryption_engine_process_downloading_file_cb(LinphoneCore *lc, LinphoneChatMessage *msg, const char *buffer, size_t size, char **decrypted_buffer);

View file

@ -7184,6 +7184,49 @@ const char *linphone_reason_to_string(LinphoneReason err){
return "unknown error";
}
LinphoneReason linphone_error_code_to_reason(int err) {
if (err == 200) {
return LinphoneReasonNone;
} else if (err == 503) {
return LinphoneReasonIOError;
} else if (err == 400) {
return LinphoneReasonUnknown;
} else if (err == 486) {
return LinphoneReasonBusy;
} else if (err == 603) {
return LinphoneReasonDeclined;
} else if (err == 600) {
return LinphoneReasonDoNotDisturb;
} else if (err == 403) {
return LinphoneReasonForbidden;
} else if (err == 415) {
return LinphoneReasonUnsupportedContent;
} else if (err == 404) {
return LinphoneReasonNotFound;
} else if (err == 480) {
return LinphoneReasonTemporarilyUnavailable;
} else if (err == 401) {
return LinphoneReasonUnauthorized;
} else if (err == 488) {
return LinphoneReasonNotAcceptable;
} else if (err == 481) {
return LinphoneReasonNoMatch;
} else if (err == 301) {
return LinphoneReasonMovedPermanently;
} else if (err == 410) {
return LinphoneReasonGone;
} else if (err == 484) {
return LinphoneReasonAddressIncomplete;
} else if (err == 501) {
return LinphoneReasonNotImplemented;
} else if (err == 504) {
return LinphoneReasonServerTimeout;
} else if (err == 502) {
return LinphoneReasonBadGateway;
}
return LinphoneReasonUnknown;
}
const char *linphone_error_to_string(LinphoneReason err){
return linphone_reason_to_string(err);
}

View file

@ -227,6 +227,12 @@ typedef enum _LinphoneReason LinphoneReason;
**/
LINPHONE_PUBLIC const char *linphone_reason_to_string(LinphoneReason err);
/**
* Converts a error code to a LinphoneReason.
* @ingroup misc
**/
LINPHONE_PUBLIC LinphoneReason linphone_error_code_to_reason(int err);
/**
* Object representing full details about a signaling error or status.
* All LinphoneErrorInfo object returned by the liblinphone API are readonly and transcients. For safety they must be used immediately
@ -1639,7 +1645,7 @@ LINPHONE_PUBLIC uint32_t linphone_chat_room_get_char(const LinphoneChatRoom *cr)
*
* @return true if zrtp secrets have already been shared and ready to use
*/
LINPHONE_PUBLIC bool_t linphone_chat_room_lime_available(LinphoneChatRoom *cr);
LINPHONE_PUBLIC bool_t linphone_chat_room_lime_available(LinphoneChatRoom *cr);
/**
* Returns an list of chat rooms

View file

@ -549,7 +549,7 @@ LINPHONE_PUBLIC void linphone_core_get_local_ip(LinphoneCore *lc, int af, const
LinphoneProxyConfig *linphone_proxy_config_new_from_config_file(LinphoneCore *lc, int index);
void linphone_proxy_config_write_to_config_file(struct _LpConfig* config,LinphoneProxyConfig *obj, int index);
void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessage *msg);
LinphoneReason linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessage *msg);
void linphone_core_is_composing_received(LinphoneCore *lc, SalOp *op, const SalIsComposing *is_composing);
void linphone_core_real_time_text_received(LinphoneCore *lc, LinphoneChatRoom *cr, uint32_t character, LinphoneCall *call);