mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-05-07 05:53:06 +00:00
Reworked im encryption engine to be at linphone level instead of sal level
This commit is contained in:
parent
e8258de05b
commit
3214b4371a
9 changed files with 241 additions and 204 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
168
coreapi/chat.c
168
coreapi/chat.c
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
106
coreapi/lime.c
106
coreapi/lime.c
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue