From 6bdc64962406949861f18981fb7be5890d67883a Mon Sep 17 00:00:00 2001 From: Johan Pascal Date: Thu, 12 Jun 2014 00:49:36 +0200 Subject: [PATCH] Add encrypted file transfer message + test for the encrypted text message + fix bug introduced in last merge --- coreapi/bellesip_sal/sal_op_message.c | 27 ++++-- coreapi/chat.c | 119 ++++++++++++++++++++++++-- coreapi/help/filetransfer.c | 26 +++--- coreapi/info.c | 13 +++ coreapi/lime.c | 50 +++++++++++ coreapi/lime.h | 28 ++++++ coreapi/linphonecore.h | 2 + tester/ZIDCacheAlice.xml | 2 +- tester/ZIDCacheBob.xml | 4 +- tester/message_tester.c | 118 +++++++++++++++++++++---- 10 files changed, 336 insertions(+), 53 deletions(-) diff --git a/coreapi/bellesip_sal/sal_op_message.c b/coreapi/bellesip_sal/sal_op_message.c index 18db3dbd2..3e0100b4c 100644 --- a/coreapi/bellesip_sal/sal_op_message.c +++ b/coreapi/bellesip_sal/sal_op_message.c @@ -61,8 +61,8 @@ static void process_response_event(void *op_base, const belle_sip_response_event } 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; + 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) { @@ -71,8 +71,11 @@ static bool_t is_plain_text(belle_sip_header_content_type_t* content_type) { } static bool_t is_cipher_xml(belle_sip_header_content_type_t* content_type) { - return strcmp("xml",belle_sip_header_content_type_get_type(content_type))==0 - && strcmp("cipher",belle_sip_header_content_type_get_subtype(content_type))==0; + return (strcmp("xml",belle_sip_header_content_type_get_type(content_type))==0 + && strcmp("cipher",belle_sip_header_content_type_get_subtype(content_type))==0) + + || (strcmp("application",belle_sip_header_content_type_get_type(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_external_body(belle_sip_header_content_type_t* content_type) { return strcmp("message",belle_sip_header_content_type_get_type(content_type))==0 @@ -84,7 +87,7 @@ static bool_t is_im_iscomposing(belle_sip_header_content_type_t* content_type) { } static void add_message_accept(belle_sip_message_t *msg){ - belle_sip_message_add_header(msg,belle_sip_header_create("Accept","text/plain, message/external-body, application/im-iscomposing+xml, xml/cioher, application/vnd.gsma.rcs-ft-http+xml")); + belle_sip_message_add_header(msg,belle_sip_header_create("Accept","text/plain, message/external-body, application/im-iscomposing+xml, xml/cipher, application/vnd.gsma.rcs-ft-http+xml, application/cipher.vnd.gsma.rcs-ft-http+xml")); } void sal_process_incoming_message(SalOp *op,const belle_sip_request_event_t *event){ @@ -148,10 +151,12 @@ void sal_process_incoming_message(SalOp *op,const belle_sip_request_event_t *eve } } + + rcs_filetransfer=is_rcs_filetransfer(content_type); if (content_type && ((plain_text=is_plain_text(content_type)) || (external_body=is_external_body(content_type)) || (decryptedMessage!=NULL) - || (rcs_filetransfer=is_rcs_filetransfer(content_type)))) { + || rcs_filetransfer)) { SalMessage salmsg; char message_id[256]={0}; @@ -166,8 +171,12 @@ void sal_process_incoming_message(SalOp *op,const belle_sip_request_event_t *eve ,belle_sip_header_call_id_get_call_id(call_id) ,belle_sip_header_cseq_get_seq_number(cseq)); salmsg.from=from; - salmsg.text=(plain_text||rcs_filetransfer)?belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)):(cipher_xml?(char *)decryptedMessage:NULL); - salmsg.text=(plain_text||rcs_filetransfer)?belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)):NULL; + /* 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.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 */ @@ -235,7 +244,7 @@ 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) { + 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, "r+"); diff --git a/coreapi/chat.c b/coreapi/chat.c index 9c7050ff2..b66334262 100644 --- a/coreapi/chat.c +++ b/coreapi/chat.c @@ -26,6 +26,8 @@ #include "private.h" #include "lpconfig.h" #include "belle-sip/belle-sip.h" +#include "lime.h" +#include "ortp/b64.h" #define COMPOSING_DEFAULT_IDLE_TIMEOUT 15 #define COMPOSING_DEFAULT_REFRESH_TIMEOUT 60 @@ -42,6 +44,7 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatM #define MULTIPART_END "\r\n--" MULTIPART_BOUNDARY "--\r\n" const char *multipart_boundary=MULTIPART_BOUNDARY; +#define FILE_TRANSFER_KEY_SIZE 32 static size_t linphone_chat_message_compute_multipart_header_size(const char *filename, const char *content_type) { return strlen(MULTIPART_HEADER_1)+strlen(filename)+strlen(MULTIPART_HEADER_2)+strlen(content_type)+strlen(MULTIPART_HEADER_3); } @@ -98,12 +101,34 @@ static int linphone_chat_message_file_transfer_on_send_body(belle_sip_user_body_ *size=partlen; }else if (offsetvtable.file_transfer_send(lc, chatMsg, chatMsg->file_transfer_information, buffer, size); + if (chatMsg->file_transfer_information->key != NULL) { /* if we have a key to cipher the message, use it! */ + /* get data from callback to a plainBuffer */ + /* if this chunk is not the last one, the lenght must be a multiple of block cipher size(16 bytes)*/ + if (offset+*sizevtable.file_transfer_send(lc, chatMsg, chatMsg->file_transfer_information, plainBuffer, size); + lime_encryptFile(&(chatMsg->file_transfer_information->cryptoContext), chatMsg->file_transfer_information->key, *size, plainBuffer, buffer); + free(plainBuffer); + } else { + /* get data from call back directly to the output buffer */ + lc->vtable.file_transfer_send(lc, chatMsg, chatMsg->file_transfer_information, buffer, size); + } + /* DEBUG DEBUG : THIS SHALL NEVER HAPPEND */ + if (*size == 0) { + exit(1); + } }else{ + /* conclude the file ciphering if needed */ + if (chatMsg->file_transfer_information->key != NULL) { + lime_encryptFile(&(chatMsg->file_transfer_information->cryptoContext), NULL, 0, NULL, NULL); + } + *size=strlen(MULTIPART_END); strncpy(buffer,MULTIPART_END,*size); } + belle_sip_free(content_type); return BELLE_SIP_CONTINUE; } @@ -123,6 +148,12 @@ static void linphone_chat_message_process_response_from_post_file(void *data, co if (event->response){ int code=belle_http_response_get_status_code(event->response); if (code == 204) { /* this is the reply to the first post to the server - an empty message */ + /* shall we encrypt the file */ + if (msg->chat_room->lc->lime == 1) { + /* generate a random 192 bits key + 64 bits of initial vector and store it into the file_transfer_information->key field of the message */ + msg->file_transfer_information->key = (unsigned char *)malloc(FILE_TRANSFER_KEY_SIZE); + sal_get_random_bytes(msg->file_transfer_information->key, FILE_TRANSFER_KEY_SIZE); + } /* start uploading the file */ belle_http_request_listener_callbacks_t cbs={0}; belle_http_request_listener_t *l; @@ -150,7 +181,46 @@ static void linphone_chat_message_process_response_from_post_file(void *data, co } if (code == 200 ) { /* file has been uplaoded correctly, get server reply and send it */ const char *body = belle_sip_message_get_body((belle_sip_message_t *)event->response); - msg->message = ms_strdup(body); + + /* if we have an encryption key for the file, we must insert it into the message */ + if (msg->file_transfer_information->key != NULL) { + /* parse the message body */ + xmlDocPtr xmlMessageBody = xmlParseDoc((const xmlChar *)body); + + xmlNodePtr cur = xmlDocGetRootElement(xmlMessageBody); + if (cur != NULL) { + cur = cur->xmlChildrenNode; + while (cur!=NULL) { + if (!xmlStrcmp(cur->name, (const xmlChar *)"file-info")) { /* we found a file info node, check it has a type="file" attribute */ + xmlChar *typeAttribute = xmlGetProp(cur, (const xmlChar *)"type"); + if(!xmlStrcmp(typeAttribute, (const xmlChar *)"file")) { /* this is the node we are looking for : add a file-key children node */ + /* convert key to base64 */ + int b64Size = b64_encode(NULL, FILE_TRANSFER_KEY_SIZE, NULL, 0); + char *keyb64 = (char *)malloc(b64Size+1); + b64Size = b64_encode(msg->file_transfer_information->key, FILE_TRANSFER_KEY_SIZE, keyb64, b64Size); + keyb64[b64Size] = '\0'; /* libxml need a null terminated string */ + + /* add the node containing the key to the file-info node */ + xmlNewTextChild(cur, NULL, (const xmlChar *)"file-key", (const xmlChar *)keyb64); + xmlFree(typeAttribute); + + /* dump the xml into msg->message */ + int xmlStringLength; + xmlDocDumpFormatMemoryEnc(xmlMessageBody, (xmlChar **)&msg->message, &xmlStringLength, "UTF-8", 0); + + break; + } + xmlFree(typeAttribute); + } + cur = cur->next; + } + } + xmlFreeDoc(xmlMessageBody); + + } else { /* no encryption key, transfer in plain, just copy the message sent by server */ + msg->message = ms_strdup(body); + } + linphone_content_uninit(msg->file_transfer_information); ms_free(msg->file_transfer_information); msg->file_transfer_information = NULL; @@ -365,7 +435,12 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatM } else { if (cr->lc->lime == 1) { /* shall we try to encrypt messages? */ linphone_chat_message_ref(msg); /* ref the message or it may be destroyed by callback if the encryption failed */ - sal_message_send(op, identity, cr->peer, "xml/cipher", msg->message, linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr))); + msg->content_type = ms_strdup("application/vnd.gsma.rcs-ft-http+xml"); + if (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*/ + sal_message_send(op, identity, cr->peer, "application/cipher.vnd.gsma.rcs-ft-http+xml", msg->message, linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr))); + } else { + sal_message_send(op, identity, cr->peer, "xml/cipher", msg->message, linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr))); + } } else { if (msg->content_type == NULL) { sal_text_send(op, identity, cr->peer,msg->message); @@ -487,6 +562,15 @@ void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessag file_url = xmlGetProp(cur, (const xmlChar *)"url"); } + if (!xmlStrcmp(cur->name, (const xmlChar *)"file-key")) { /* there is a key in the message: file has been encrypted */ + /* convert the key from base 64 */ + xmlChar *keyb64 = xmlNodeListGetString(xmlMessageBody, cur->xmlChildrenNode, 1); + int keyLength = b64_decode((char *)keyb64, strlen((char *)keyb64), NULL, 0); + msg->file_transfer_information->key = (uint8_t *)malloc(keyLength); + b64_decode((char *)keyb64, strlen((char *)keyb64), msg->file_transfer_information->key, keyLength); + xmlFree(keyb64); + } + cur=cur->next; } xmlFree(typeAttribute); @@ -944,12 +1028,27 @@ 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 *msg, void *data, size_t offset, const void *buffer, size_t size){ - //printf("Receive %ld bytes\n\n%s\n\n", size, (char *)buffer); + /* first call may be with a zero size, ignore it */ + if (size == 0) { + return; + } LinphoneChatMessage* chatMsg=(LinphoneChatMessage *)data; LinphoneCore *lc = chatMsg->chat_room->lc; - /* call back given by application level */ - if (lc->vtable.file_transfer_received != NULL) { - lc->vtable.file_transfer_received(lc, chatMsg, chatMsg->file_transfer_information, buffer, size); + + if (chatMsg->file_transfer_information->key != NULL) { /* we have a key, we must decrypt the file */ + /* get data from callback to a plainBuffer */ + char *plainBuffer = (char *)malloc(size); + lime_decryptFile(&(chatMsg->file_transfer_information->cryptoContext), chatMsg->file_transfer_information->key, size, plainBuffer, (char *)buffer); + /* call back given by application level */ + if (lc->vtable.file_transfer_received != NULL) { + lc->vtable.file_transfer_received(lc, chatMsg, chatMsg->file_transfer_information, plainBuffer, size); + } + free(plainBuffer); + } else { /* regular file, no deciphering */ + /* call back given by application level */ + if (lc->vtable.file_transfer_received != NULL) { + lc->vtable.file_transfer_received(lc, chatMsg, chatMsg->file_transfer_information, buffer, size); + } } return; @@ -979,6 +1078,10 @@ static void linphone_chat_process_response_from_get_file(void *data, const belle if (code==200) { LinphoneChatMessage* chatMsg=(LinphoneChatMessage *)data; LinphoneCore *lc = chatMsg->chat_room->lc; + /* if we the file was encrypted, finish the decryption and free context */ + if (chatMsg->file_transfer_information->key) { + lime_decryptFile(&(chatMsg->file_transfer_information->cryptoContext), NULL, 0, NULL, NULL); + } /* file downloaded succesfully, call again the callback with size at zero */ if (lc->vtable.file_transfer_received != NULL) { lc->vtable.file_transfer_received(lc, chatMsg, chatMsg->file_transfer_information, NULL, 0); diff --git a/coreapi/help/filetransfer.c b/coreapi/help/filetransfer.c index 9bbbcddeb..4af168ee3 100644 --- a/coreapi/help/filetransfer.c +++ b/coreapi/help/filetransfer.c @@ -69,20 +69,19 @@ static void file_transfer_received(LinphoneCore *lc, LinphoneChatMessage *messag /*first chunk, creating file*/ file = open("receive_file.dump",O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR); linphone_chat_message_set_user_data(message,(void*)(long)(0x00000000FFFFFFFF&file)); /*store fd for next chunks*/ - } else { - /*next chunk*/ - file = (int)((long)(linphone_chat_message_get_user_data(message))&0x00000000FFFFFFFF); + } - if (size==0) { + /*next chunk*/ + file = (int)((long)(linphone_chat_message_get_user_data(message))&0x00000000FFFFFFFF); - printf("File transfert completed\n"); - linphone_chat_room_destroy(linphone_chat_message_get_chat_room(message)); - linphone_chat_message_destroy(message); - close(file); - running=FALSE; - } else { /* store content on a file*/ - write(file,buff,size); - } + if (size==0) { + printf("File transfert completed\n"); + linphone_chat_room_destroy(linphone_chat_message_get_chat_room(message)); + linphone_chat_message_destroy(message); + close(file); + running=FALSE; + } else { /* store content on a file*/ + write(file,buff,size); } } @@ -192,9 +191,6 @@ int main(int argc, char *argv[]){ /*now create a chat message with custom content*/ LinphoneChatMessage* chat_message = linphone_chat_room_create_file_transfer_message(chat_room,&content); - if (chat_message == NULL) { - printf("returned message is null\n"); - } /*initiating file transfer*/ linphone_chat_room_send_message2(chat_room, chat_message, linphone_file_transfer_state_changed, NULL); diff --git a/coreapi/info.c b/coreapi/info.c index 2bf2b85ad..4279a963c 100644 --- a/coreapi/info.c +++ b/coreapi/info.c @@ -47,6 +47,14 @@ void linphone_content_copy(LinphoneContent *obj, const LinphoneContent *ref){ SET_STRING(obj,subtype,ref->subtype); SET_STRING(obj,encoding,ref->encoding); SET_STRING(obj,name,ref->name); + if (obj->key) { + ms_free(obj->key); + obj->key=NULL; + } + if (ref->key) { + obj->key = (unsigned char *)ms_strdup((const char *)ref->key); + } + if (obj->data) { ms_free(obj->data); obj->data=NULL; @@ -65,6 +73,7 @@ void linphone_content_uninit(LinphoneContent * obj){ if (obj->data) ms_free(obj->data); if (obj->encoding) ms_free(obj->encoding); if (obj->name) ms_free(obj->name); + if (obj->key) ms_free(obj->key); } LinphoneContent *linphone_content_copy_from_sal_body(LinphoneContent *obj, const SalBody *ref){ @@ -81,6 +90,8 @@ LinphoneContent *linphone_content_copy_from_sal_body(LinphoneContent *obj, const ((char*)obj->data)[ref->size]='\0'; } obj->size=ref->size; + obj->name = NULL; + obj->key = NULL; return obj; } @@ -91,6 +102,8 @@ const LinphoneContent *linphone_content_from_sal_body(LinphoneContent *obj, cons obj->data=(void*)ref->data; obj->encoding=(char*)ref->encoding; obj->size=ref->size; + obj->name = NULL; + obj->key = NULL; return obj; } return NULL; diff --git a/coreapi/lime.c b/coreapi/lime.c index 0e1f90031..3873a33cb 100644 --- a/coreapi/lime.c +++ b/coreapi/lime.c @@ -436,6 +436,56 @@ int lime_encryptMessage(limeKey_t *key, uint8_t *plainMessage, uint32_t messageL return 0; } + +int lime_encryptFile(void **cryptoContext, unsigned char *key, size_t length, char *plain, char *cipher) { + gcm_context *gcmContext; + + if (*cryptoContext == NULL) { /* first call to the function, allocate a crypto context and initialise it */ + gcmContext = (gcm_context *)malloc(sizeof(gcm_context)); + *cryptoContext = (void *)gcmContext; + gcm_init(gcmContext, POLARSSL_CIPHER_ID_AES, key, 192); + gcm_starts(gcmContext, GCM_ENCRYPT, key+24, 8, NULL, 0); /* key contains 192bits of key || 64 bits of Initialisation Vector */ + } else { /* this is not the first call, get the context */ + gcmContext = (gcm_context *)*cryptoContext; + } + + if (length != 0) { + gcm_update(gcmContext, length, (const unsigned char *)plain, (unsigned char *)cipher); + } else { /* lenght is 0, finish the stream */ + gcm_finish(gcmContext, NULL, 0); /* do not generate tag */ + gcm_free(gcmContext); + free(*cryptoContext); + *cryptoContext = NULL; + } + + return 0; +} + +int lime_decryptFile(void **cryptoContext, unsigned char *key, size_t length, char *plain, char *cipher) { + gcm_context *gcmContext; + + if (*cryptoContext == NULL) { /* first call to the function, allocate a crypto context and initialise it */ + gcmContext = (gcm_context *)malloc(sizeof(gcm_context)); + *cryptoContext = (void *)gcmContext; + gcm_init(gcmContext, POLARSSL_CIPHER_ID_AES, key, 192); + gcm_starts(gcmContext, GCM_DECRYPT, key+24, 8, NULL, 0); /* key contains 192bits of key || 64 bits of Initialisation Vector */ + } else { /* this is not the first call, get the context */ + gcmContext = (gcm_context *)*cryptoContext; + } + + if (length != 0) { + gcm_update(gcmContext, length, (const unsigned char *)cipher, (unsigned char *)plain); + } else { /* lenght is 0, finish the stream */ + gcm_finish(gcmContext, NULL, 0); /* do not generate tag */ + gcm_free(gcmContext); + free(*cryptoContext); + *cryptoContext = NULL; + } + + return 0; +} + + int lime_decryptMessage(limeKey_t *key, uint8_t *encryptedMessage, uint32_t messageLength, uint8_t selfZID[12], uint8_t *plainMessage) { /* Authenticated data is senderZID(12 bytes)||receiverZID(12 bytes)||sessionIndex(4 bytes) */ uint8_t authenticatedData[28]; diff --git a/coreapi/lime.h b/coreapi/lime.h index 455c80c6c..7ccb3740f 100644 --- a/coreapi/lime.h +++ b/coreapi/lime.h @@ -113,6 +113,34 @@ __attribute__ ((visibility ("default"))) int lime_deriveKey(limeKey_t *key); */ __attribute__ ((visibility ("default"))) int lime_encryptMessage(limeKey_t *key, uint8_t *plainMessage, uint32_t messageLength, uint8_t selfZID[12], uint8_t *encryptedMessage); +/** + * @brief Encrypt a file before transfering it to the server, encryption is done in several call, first one will be done with cryptoContext null, last one with length = 0 + * + * @param[in/out] cryptoContext The context used to encrypt the file using AES-GCM. Is created at first call(if null) + * @param[in] key 256 bits : 192 bits of key || 64 bits of Initial Vector + * @param[in] length Length of data to be encrypted, if 0 it will conclude the encryption + * @param[in] plain Plain data to be encrypted (length bytes) + * @param[out] cipher Output to a buffer allocated by caller, at least length bytes available + * + * @return 0 on success, error code otherwise + * + */ +__attribute__ ((visibility ("default"))) int lime_encryptFile(void **cryptoContext, unsigned char *key, size_t length, char *plain, char *cipher); + +/** + * @brief Decrypt a file retrieved from server, decryption is done in several call, first one will be done with cryptoContext null, last one with length = 0 + * + * @param[in/out] cryptoContext The context used to decrypt the file using AES-GCM. Is created at first call(if null) + * @param[in] key 256 bits : 192 bits of key || 64 bits of Initial Vector + * @param[in] length Length of data to be decrypted, if 0 it will conclude the decryption + * @param[out] plain Output to a buffer allocated by caller, at least length bytes available + * @param[in] cipher Cipher text to be decrypted(length bytes) + * + * @return 0 on success, error code otherwise + * + */ +__attribute__ ((visibility ("default"))) int lime_decryptFile(void **cryptoContext, unsigned char *key, size_t length, char *plain, char *cipher); + /** * @brief decrypt and authentify a message with the given key * diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index 4e7aa6256..55fa9f6a1 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -138,6 +138,8 @@ struct _LinphoneContent{ When provided by callback #LinphoneCoreFileTransferSendCb or #LinphoneCoreFileTransferReceiveCb, it states the total number of bytes of the transfered file*/ char *encoding; /** -ef7692d0792a67491ae2d44e005dbe0399643d953a2202dd9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899pipo1@pipo.comf6e5c94feabbe348f25a528cc990b7ec0f3390286314eb70cf2a9a852afb2df4bfd9ac653a83c4559cb0ae7394e7cd3b2d3c57bb28e62068d2df23e8f9b771935f9aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193bcffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b7719300000074000001a21234567889643d953a2202ee9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899pipo1@pipo.comb438386ce7d91f0c3341315ff58ce14826a119f36d91650ca26fa7fde2f1601225d9ac653a83c4559cb0ae7394e7cd3b2d3c57bb28e62068d2df23e8f9b77193f69aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b7719322ffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b771930000000c00000000 +ef7692d0792a67491ae2d44e005dbe0399643d953a2202dd9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899sip:pauline@sip.example.org6cac6d8e4453ccf70749674c421b7ca434d300ca30265a9a86b2979c32bdd1595b91adffd91fcfa5b9cc6907a7d59bd5c21ffe8d508b4d6c536cb73329c914c35f9aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193bcffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b7719300000077000001c61234567889643d953a2202ee9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899sip:pauline@sip.example.org72d80ab1cad243cf45634980c1d02cfb2df81ce0dd5dfcf1ebeacfc5345a917625d9ac653a83c4559cb0ae7394e7cd3b2d3c57bb28e62068d2df23e8f9b77193f69aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b7719322ffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b771930000000f00000000 diff --git a/tester/ZIDCacheBob.xml b/tester/ZIDCacheBob.xml index 23116d8da..31ff1393a 100644 --- a/tester/ZIDCacheBob.xml +++ b/tester/ZIDCacheBob.xml @@ -1,4 +1,4 @@ 005dbe0399643d953a2202dd - ef7692d0792a67491ae2d44e9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899pipo1@pipo.comf6e5c94feabbe348f25a528cc990b7ec0f3390286314eb70cf2a9a852afb2df4bfd9ac653a83c4559cb0ae7394e7cd3b2d3c57bb28e62068d2df23e8f9b771935f9aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193bcffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b7719300000074000001a2 - 1234567889643d953a2202ee9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899pipo1@pipo.com123456789012345678901234567890123456765431262068d2df23e8f9b7719325d9ac653a83c4559cb0ae7394e7cd3b2d3c57bb28e62068d2df23e8f9b77193f69aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b7719322ffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b771930000000100000000 + ef7692d0792a67491ae2d44e9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899sip:marie@sip.example.org6cac6d8e4453ccf70749674c421b7ca434d300ca30265a9a86b2979c32bdd1595b91adffd91fcfa5b9cc6907a7d59bd5c21ffe8d508b4d6c536cb73329c914c35f9aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193bcffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b7719300000077000001c6 + 1234567889643d953a2202ee9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899sip:marie@sip.example.org21397a0d145badd58b3073ba0f537cab1bc97ca7de1f0d2db9a57fc3f63b74b725d9ac653a83c4559cb0ae7394e7cd3b2d3c57bb28e62068d2df23e8f9b77193f69aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b7719322ffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b771930000002500000000 diff --git a/tester/message_tester.c b/tester/message_tester.c index 613fc82c4..ba5272e30 100644 --- a/tester/message_tester.c +++ b/tester/message_tester.c @@ -62,27 +62,26 @@ void message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMess * */ void file_transfer_received(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, const char* buff, size_t size){ int file=-1; + /* first chunk, creating file */ if (!linphone_chat_message_get_user_data(message)) { - /*first chunk, creating file*/ file = open("receive_file.dump",O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR); linphone_chat_message_set_user_data(message,(void*)(long)(0x00000000FFFFFFFF&file)); /*store fd for next chunks*/ - } else { - /*next chunk*/ - file = (int)((long)(linphone_chat_message_get_user_data(message))&0x00000000FFFFFFFF); + } - if (size==0) { /* tranfer complerte */ - linphone_chat_room_destroy(linphone_chat_message_get_chat_room(message)); - linphone_chat_message_destroy(message); - stats* counters = get_stats(lc); - counters->number_of_LinphoneMessageExtBodyReceived++; - close(file); - } else { /* store content on a file*/ - write(file,buff,size); - } + file = (int)((long)(linphone_chat_message_get_user_data(message))&0x00000000FFFFFFFF); + + if (size==0) { /* tranfer complete */ + linphone_chat_room_destroy(linphone_chat_message_get_chat_room(message)); + linphone_chat_message_destroy(message); + stats* counters = get_stats(lc); + counters->number_of_LinphoneMessageExtBodyReceived++; + close(file); + } else { /* store content on a file*/ + write(file,buff,size); } } -static char big_file [128000]; /* a buffer to simulate a big file for the file transfer message test */ +char big_file[128000]; /* a buffer to simulate a big file for the file transfer message test */ /* * function called when the file transfer is initiated. file content should be feed into object LinphoneContent @@ -364,9 +363,13 @@ static void file_transfer_message(void) { int i; /* setting dummy file content to something */ const char* big_file_content="big file"; - for (i=0;ilc, 1); + linphone_core_set_lime(pauline->lc, 1); + + /* set the zid caches files */ + linphone_core_set_zrtp_secrets_file(marie->lc, "ZIDCacheAlice.xml"); + linphone_core_set_zrtp_secrets_file(pauline->lc, "ZIDCacheBob.xml"); + + /* Globally configure an http file transfer server. */ + linphone_core_set_file_transfer_server(pauline->lc,"https://www.linphone.org:444/lft.php"); + + /* create a chatroom on pauline's side */ + char* to = linphone_address_as_string(marie->identity); + LinphoneChatRoom* chat_room = linphone_core_create_chat_room(pauline->lc,to); + + /* create a file transfer message */ + LinphoneContent content; + memset(&content,0,sizeof(content)); + content.type="text"; + content.subtype="plain"; + content.size=sizeof(big_file); /*total size to be transfered*/ + content.name = "bigfile.txt"; + LinphoneChatMessage* message = linphone_chat_room_create_file_transfer_message(chat_room, &content); + + linphone_chat_room_send_message2(chat_room,message,liblinphone_tester_chat_message_state_change,pauline->lc); + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageExtBodyReceived,1)); + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageDelivered,1)); + + CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,1); + CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageExtBodyReceived,1); + + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + + static void text_message_with_send_error(void) { LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); @@ -567,7 +619,7 @@ void printHex(char *title, uint8_t *data, uint32_t length) { printf ("\n"); } -static void lime(void) { +static void lime_unit(void) { int retval; /* Load Alice cache file */ FILE *CACHE = fopen("ZIDCacheAlice.xml", "r+"); @@ -599,7 +651,7 @@ static void lime(void) { /* encrypt a message */ uint8_t *multipartMessage = NULL; - retval = lime_createMultipartMessage(cacheBufferAlice, (uint8_t *)"Bonjour les petits lapins,ca va? éh oui oui", (uint8_t *)"pipo1@pipo.com", &multipartMessage); + retval = lime_createMultipartMessage(cacheBufferAlice, (uint8_t *)"Bonjour les petits lapins,ca va? éh oui oui", (uint8_t *)"sip:pauline@sip.example.org", &multipartMessage); printf("create message return %d\n", retval); if (retval == 0) { @@ -720,6 +772,34 @@ static void lime(void) { xmlFreeDoc(cacheBuffer); } +static void lime_text_message(void) { + LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); + + /* make sure lime is enabled */ + linphone_core_set_lime(marie->lc, 1); + linphone_core_set_lime(pauline->lc, 1); + + /* set the zid caches files */ + linphone_core_set_zrtp_secrets_file(marie->lc, "ZIDCacheAlice.xml"); + linphone_core_set_zrtp_secrets_file(pauline->lc, "ZIDCacheBob.xml"); + + char* to = linphone_address_as_string(marie->identity); + LinphoneChatRoom* chat_room = linphone_core_create_chat_room(pauline->lc,to); + ms_free(to); + + linphone_chat_room_send_message(chat_room,"Bla bla bla bla"); + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1)); + CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageReceivedLegacy,1); + + CU_ASSERT_PTR_NOT_NULL(linphone_core_get_chat_room(marie->lc,pauline->identity)); + /* TODO : check the message arrived correctly deciphered */ + + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + + #ifdef MSG_STORAGE_ENABLED /* @@ -813,11 +893,13 @@ test_t message_tests[] = { { "Text message with send error", text_message_with_send_error }, { "Text message with external body", text_message_with_external_body }, { "File transfer message", file_transfer_message }, + { "Lime File transfer message", lime_file_transfer_message }, { "Text message denied", text_message_denied }, { "Info message", info_message }, { "Info message with body", info_message_with_body }, { "IsComposing notification", is_composing_notification }, - { "Lime", lime } + { "Lime Unitary", lime_unit }, + { "Lime Text Message", lime_text_message } #ifdef MSG_STORAGE_ENABLED ,{ "Database migration", message_storage_migration } #endif