From fcc61d1aa5727d5bffb08cfd58cefadf02ef31fa Mon Sep 17 00:00:00 2001 From: Johan Pascal Date: Sat, 1 Apr 2017 11:05:08 +0700 Subject: [PATCH 01/18] Switch to sql based zrtp/lime cache Warning: no migration from old xml cache provided yet --- coreapi/lime.c | 747 ++++++++++++++++------------------------ coreapi/lime.h | 36 +- coreapi/linphonecall.c | 11 +- coreapi/linphonecore.c | 75 ++++ coreapi/private.h | 4 +- gtk/main.c | 38 +- include/linphone/core.h | 23 +- mediastreamer2 | 2 +- tester/message_tester.c | 427 +++++------------------ 9 files changed, 549 insertions(+), 814 deletions(-) diff --git a/coreapi/lime.c b/coreapi/lime.c index d8b33e9aa..79ec908ad 100644 --- a/coreapi/lime.c +++ b/coreapi/lime.c @@ -1,6 +1,6 @@ /* linphone -Copyright (C) 2015 Belledonne Communications SARL +Copyright (C) 2017 Belledonne Communications SARL This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -26,6 +26,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "private.h" #include "bctoolbox/crypto.h" #include "bctoolbox/port.h" +#include "bzrtp/bzrtp.h" #define FILE_TRANSFER_KEY_SIZE 32 @@ -36,55 +37,16 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ bool_t lime_is_available(void) { return TRUE; } -/** - * @brief Retrieve selfZID from cache - * - * @param[in] cacheBuffer The xmlDoc containing current cache - * @param[out] selfZid The ZID found as a 24 hexa char string null terminated - * - * @return 0 on success, error code otherwise - */ -static int lime_getSelfZid(xmlDocPtr cacheBuffer, uint8_t selfZid[25]) { - xmlNodePtr cur; - xmlChar *selfZidHex; - - if (cacheBuffer == NULL ) { - return LIME_INVALID_CACHE; - } - - cur = xmlDocGetRootElement(cacheBuffer); - /* if we found a root element, parse its children node */ - if (cur!=NULL) - { - cur = cur->xmlChildrenNode; - } - selfZidHex = NULL; - while (cur!=NULL) { - if ((!xmlStrcmp(cur->name, (const xmlChar *)"selfZID"))){ /* self ZID found, extract it */ - selfZidHex = xmlNodeListGetString(cacheBuffer, cur->xmlChildrenNode, 1); - /* copy it to the output buffer and add the null termination */ - memcpy(selfZid, selfZidHex, 24); - selfZid[24]='\0'; - break; - } - cur = cur->next; - } - - /* did we found a ZID? */ - if (selfZidHex == NULL) { - return LIME_INVALID_CACHE; - } - - xmlFree(selfZidHex); - return 0; -} - -int lime_getCachedSndKeysByURI(xmlDocPtr cacheBuffer, limeURIKeys_t *associatedKeys) { - xmlNodePtr cur; +int lime_getCachedSndKeysByURI(void *cachedb, limeURIKeys_t *associatedKeys) { + sqlite3 *db = (sqlite3 *)cachedb; size_t keysFound = 0; /* used to detect the no key found error because of validity expired */ + char *stmt = NULL; + int ret; + sqlite3_stmt *sqlStmt = NULL; + int length =0; + uint8_t pvsOne[1] = {0x01}; /* used to bind this specific byte value to a blob WHERE constraint in the query */ - /* parse the file to get all peer matching the sipURI given in associatedKeys*/ - if (cacheBuffer == NULL ) { /* there is no cache return error */ + if (cachedb == NULL ) { /* there is no cache return error */ return LIME_INVALID_CACHE; } @@ -92,111 +54,115 @@ int lime_getCachedSndKeysByURI(xmlDocPtr cacheBuffer, limeURIKeys_t *associatedK associatedKeys->associatedZIDNumber = 0; associatedKeys->peerKeys = NULL; - cur = xmlDocGetRootElement(cacheBuffer); - /* if we found a root element, parse its children node */ - if (cur!=NULL) - { - cur = cur->xmlChildrenNode; - } - while (cur!=NULL) { /* loop on all peer nodes */ - uint8_t matchingURIFlag = 0; /* this flag is set to one if we found the requested sipURI in the current peer node */ - if ((!xmlStrcmp(cur->name, (const xmlChar *)"peer"))) { /* found a peer node, check if there is a matching sipURI node in it */ - xmlNodePtr peerNodeChildren = cur->xmlChildrenNode; - matchingURIFlag = 0; - - /* loop on children nodes until the end or we found the matching sipURI */ - while (peerNodeChildren!=NULL && matchingURIFlag==0) { - if (!xmlStrcmp(peerNodeChildren->name, (const xmlChar *)"uri")) { /* found a peer an URI node, check the content */ - xmlChar *uriNodeContent = xmlNodeListGetString(cacheBuffer, peerNodeChildren->xmlChildrenNode, 1); - if (!xmlStrcmp(uriNodeContent, (const xmlChar *)associatedKeys->peerURI)) { /* found a match with requested URI */ - matchingURIFlag=1; - } - xmlFree(uriNodeContent); - } - peerNodeChildren = peerNodeChildren->next; - } - - if (matchingURIFlag == 1) { /* we found a match for the URI in this peer node, extract the keys, session Id, index values and key validity period */ - /* allocate a new limeKey_t structure to hold the retreived keys */ - limeKey_t *currentPeerKeys = (limeKey_t *)malloc(sizeof(limeKey_t)); - uint8_t itemFound = 0; /* count the item found, we must get all of the requested infos: 5 nodes*/ - uint8_t pvs = 0; - uint8_t keyValidityFound = 0; /* flag raised when we found a key validity in the cache */ - bctoolboxTimeSpec currentTimeSpec; - bctoolboxTimeSpec validityTimeSpec; /* optionnal(backward compatibility) tag for key validity */ - validityTimeSpec.tv_sec=0; - validityTimeSpec.tv_nsec=0; - - peerNodeChildren = cur->xmlChildrenNode; /* reset peerNodeChildren to the first child of node */ - while (peerNodeChildren!=NULL && itemFound<6) { - xmlChar *nodeContent = NULL; - if (!xmlStrcmp(peerNodeChildren->name, (const xmlChar *)"ZID")) { - nodeContent = xmlNodeListGetString(cacheBuffer, peerNodeChildren->xmlChildrenNode, 1); - bctbx_strToUint8(currentPeerKeys->peerZID, nodeContent, 24); - itemFound++; - } - - if (!xmlStrcmp(peerNodeChildren->name, (const xmlChar *)"sndKey")) { - nodeContent = xmlNodeListGetString(cacheBuffer, peerNodeChildren->xmlChildrenNode, 1); - bctbx_strToUint8(currentPeerKeys->key, nodeContent, 64); - itemFound++; - } - if (!xmlStrcmp(peerNodeChildren->name, (const xmlChar *)"sndSId")) { - nodeContent = xmlNodeListGetString(cacheBuffer, peerNodeChildren->xmlChildrenNode, 1); - bctbx_strToUint8(currentPeerKeys->sessionId, nodeContent, 64); - itemFound++; - } - if (!xmlStrcmp(peerNodeChildren->name, (const xmlChar *)"sndIndex")) { - uint8_t sessionIndexBuffer[4]; /* session index is a uint32_t but we first retrieved it as an hexa string, convert it to a 4 uint8_t buffer */ - nodeContent = xmlNodeListGetString(cacheBuffer, peerNodeChildren->xmlChildrenNode, 1); - bctbx_strToUint8(sessionIndexBuffer, nodeContent, 8); - /* convert it back to a uint32_t (MSByte first)*/ - currentPeerKeys->sessionIndex = sessionIndexBuffer[3] + (sessionIndexBuffer[2]<<8) + (sessionIndexBuffer[1]<<16) + (sessionIndexBuffer[0]<<24); - itemFound++; - } - if (!xmlStrcmp(peerNodeChildren->name, (const xmlChar *)"pvs")) { - nodeContent = xmlNodeListGetString(cacheBuffer, peerNodeChildren->xmlChildrenNode, 1); - bctbx_strToUint8(&pvs, nodeContent, 2); /* pvs is retrieved as a 2 characters hexa string, convert it to an int8 */ - itemFound++; - } - if (!xmlStrcmp(peerNodeChildren->name, (const xmlChar *)"valid")) { - nodeContent = xmlNodeListGetString(cacheBuffer, peerNodeChildren->xmlChildrenNode, 1); - validityTimeSpec.tv_sec = bctbx_strToUint64(nodeContent); /* validity is retrieved as a 16 characters hexa string, convert it to an uint64 */ - itemFound++; - keyValidityFound = 1; - } - - xmlFree(nodeContent); - peerNodeChildren = peerNodeChildren->next; - } - - /* key validity may not be present in cache(transition from older versions), so check this, if not found-> set it to 0 wich means valid for ever */ - if (keyValidityFound == 0) { - itemFound++; - validityTimeSpec.tv_sec = 0; - } - - /* check if we have all the requested information and the PVS flag is set to 1 and key is still valid*/ - bctbx_get_utc_cur_time(¤tTimeSpec); - if (itemFound == 6 && pvs == 1) { - keysFound++; - if (validityTimeSpec.tv_sec == 0 || bctbx_timespec_compare(¤tTimeSpec, &validityTimeSpec)<0) { - associatedKeys->associatedZIDNumber +=1; - /* extend array of pointer to limeKey_t structures to add the one we found */ - associatedKeys->peerKeys = (limeKey_t **)realloc(associatedKeys->peerKeys, (associatedKeys->associatedZIDNumber)*sizeof(limeKey_t *)); - - /* add the new entry at the end */ - associatedKeys->peerKeys[associatedKeys->associatedZIDNumber-1] = currentPeerKeys; - } else { - free(currentPeerKeys); - } - } else { - free(currentPeerKeys); - } - } + /* query the DB: join ziduri, lime and zrtp tables : retrieve zuid(for easier key update in cache), peerZID, sndKey, sndSId, sndIndex, valid where self and peer ZIDs are matching constraint and pvs is raised */ + /* Note: retrieved potentially expired keys, just to be able to send a different status to caller(no keys found is not expired key found) */ + /* if we do not have self uri in associatedKeys, just retrieve any available key matching peer URI */ + if (associatedKeys->selfURI == NULL) { + stmt = sqlite3_mprintf("SELECT zu.zuid, zu.zid as peerZID, l.sndkey, l.sndSId, l.sndIndex, l.valid FROM ziduri as zu LEFT JOIN zrtp as z ON z.zuid=zu.zuid LEFT JOIN lime as l ON z.zuid=l.zuid WHERE zu.peeruri=? AND z.pvs=?;"); + ret = sqlite3_prepare_v2(db, stmt, -1, &sqlStmt, NULL); + sqlite3_free(stmt); + if (ret != SQLITE_OK) { + return LIME_INVALID_CACHE; } - cur = cur->next; + sqlite3_bind_text(sqlStmt, 1, associatedKeys->peerURI,-1, SQLITE_TRANSIENT); + sqlite3_bind_blob(sqlStmt, 2, pvsOne, 1, SQLITE_TRANSIENT); + } else { /* we have a self URI, so include it in the query */ + stmt = sqlite3_mprintf("SELECT zu.zuid, zu.zid as peerZID, l.sndkey, l.sndSId, l.sndIndex, l.valid FROM ziduri as zu LEFT JOIN zrtp as z ON z.zuid=zu.zuid LEFT JOIN lime as l ON z.zuid=l.zuid WHERE zu.selfuri=? AND zu.peeruri=? AND z.pvs=?;"); + ret = sqlite3_prepare_v2(db, stmt, -1, &sqlStmt, NULL); + sqlite3_free(stmt); + if (ret != SQLITE_OK) { + return LIME_INVALID_CACHE; + } + sqlite3_bind_text(sqlStmt, 1, associatedKeys->selfURI,-1, SQLITE_TRANSIENT); + sqlite3_bind_text(sqlStmt, 2, associatedKeys->peerURI,-1, SQLITE_TRANSIENT); + sqlite3_bind_blob(sqlStmt, 3, pvsOne, 1, SQLITE_TRANSIENT); } + + /* parse all retrieved rows */ + while ((ret = sqlite3_step(sqlStmt)) == SQLITE_ROW) { + /* allocate a new limeKey_t structure to hold the retreived keys */ + limeKey_t *currentPeerKey = (limeKey_t *)bctbx_malloc0(sizeof(limeKey_t)); + bctoolboxTimeSpec currentTimeSpec; + bctoolboxTimeSpec validityTimeSpec; + validityTimeSpec.tv_sec=0; + validityTimeSpec.tv_nsec=0; + + /* get zuid from column 0 */ + currentPeerKey->zuid = sqlite3_column_int(sqlStmt, 0); + + /* retrieve values : peerZid, sndKey, sndSId, sndIndex, valid from columns 1,2,3,4,5 */ + length = sqlite3_column_bytes(sqlStmt, 1); + if (length==12) { /* peerZID */ + memcpy(currentPeerKey->peerZID, sqlite3_column_blob(sqlStmt, 1), length); + } else { /* something wrong with that one, skip it */ + continue; + } + + length = sqlite3_column_bytes(sqlStmt, 2); + if (length==32) { /* sndKey */ + memcpy(currentPeerKey->key, sqlite3_column_blob(sqlStmt, 2), length); + } else { /* something wrong with that one, skip it */ + continue; + } + + length = sqlite3_column_bytes(sqlStmt, 3); + if (length==32) { /* sndSId */ + memcpy(currentPeerKey->sessionId, sqlite3_column_blob(sqlStmt, 3), length); + } else { /* something wrong with that one, skip it */ + continue; + } + + length = sqlite3_column_bytes(sqlStmt, 4); + if (length==4) { /* sndIndex : 4 bytes of a uint32_t, stored as a blob in big endian */ + uint8_t *sessionId = (uint8_t *)sqlite3_column_blob(sqlStmt, 4); + currentPeerKey->sessionIndex = ((uint32_t)(sessionId[0]))<<24 | + ((uint32_t)(sessionId[1]))<<16 | + ((uint32_t)(sessionId[2]))<<8 | + ((uint32_t)(sessionId[3])); + } else { /* something wrong with that one, skip it */ + continue; + } + + length = sqlite3_column_bytes(sqlStmt, 5); + if (length==8) { /* sndIndex : 8 bytes of a int64_t, stored as a blob in big endian */ + uint8_t *validity = (uint8_t *)sqlite3_column_blob(sqlStmt, 5); + validityTimeSpec.tv_sec = ((uint64_t)(validity[0]))<<56 | + ((uint64_t)(validity[1]))<<48 | + ((uint64_t)(validity[2]))<<40 | + ((uint64_t)(validity[3]))<<32 | + ((uint64_t)(validity[4]))<<24 | + ((uint64_t)(validity[5]))<<16 | + ((uint64_t)(validity[6]))<<8 | + ((uint64_t)(validity[7])); + } else { /* something wrong with that one, skip it */ + continue; + } + + /* count is a found even if it may be expired */ + keysFound++; + + /* check validity */ + bctbx_get_utc_cur_time(¤tTimeSpec); + if (validityTimeSpec.tv_sec == 0 || bctbx_timespec_compare(¤tTimeSpec, &validityTimeSpec)<0) { + associatedKeys->associatedZIDNumber +=1; + /* extend array of pointer to limeKey_t structures to add the one we found */ + associatedKeys->peerKeys = (limeKey_t **)bctbx_realloc(associatedKeys->peerKeys, (associatedKeys->associatedZIDNumber)*sizeof(limeKey_t *)); + + /* add the new entry at the end */ + associatedKeys->peerKeys[associatedKeys->associatedZIDNumber-1] = currentPeerKey; + } else { + free(currentPeerKey); + } + } + + sqlite3_finalize(sqlStmt); + + /* something is wrong with the cache? */ + if (ret!=SQLITE_DONE) { + return LIME_INVALID_CACHE; + } + + /* we're done, check what we have */ if (associatedKeys->associatedZIDNumber == 0) { if (keysFound == 0) { return LIME_NO_VALID_KEY_FOUND_FOR_PEER; @@ -205,179 +171,128 @@ int lime_getCachedSndKeysByURI(xmlDocPtr cacheBuffer, limeURIKeys_t *associatedK } } return 0; + } -int lime_getCachedRcvKeyByZid(xmlDocPtr cacheBuffer, limeKey_t *associatedKey) { - uint8_t peerZidHex[25]; - /* to check we collect all the information needed from the cache and that pvs(boolean for previously verified Sas) is set in cache */ - uint8_t itemFound = 0; - uint8_t pvs = 0; - xmlNodePtr cur; +int lime_getCachedRcvKeyByZid(void *cachedb, limeKey_t *associatedKey, const char *selfURI, const char *peerURI) { + sqlite3 *db = (sqlite3 *)cachedb; + char *stmt = NULL; + int ret; + sqlite3_stmt *sqlStmt = NULL; + int length =0; + uint8_t pvsOne[1] = {0x01}; /* used to bind this specific byte value to a blob WHERE constraint in the query */ - if (cacheBuffer == NULL ) { /* there is no cache return error */ + + if (db == NULL) { /* there is no cache return error */ return LIME_INVALID_CACHE; } - /* get the given ZID into hex format */ - bctbx_int8ToStr(peerZidHex, associatedKey->peerZID, 12); - peerZidHex[24]='\0'; /* must be a null terminated string */ - - cur = xmlDocGetRootElement(cacheBuffer); - /* if we found a root element, parse its children node */ - if (cur!=NULL) - { - cur = cur->xmlChildrenNode; - + /* query the DB: join ziduri, lime and zrtp tables : */ + /* retrieve zuid(for easier key update in cache), rcvKey, rcvSId, rcvIndex where self/peer uris and peer zid are matching constraint(unique row) and pvs is raised */ + /* Note: retrieved potentially expired keys, just to be able to send a different status to caller(no keys found is not expired key found) */ + /* if we do not have self uri in associatedKeys, just retrieve any available key matching peer URI */ + stmt = sqlite3_mprintf("SELECT zu.zuid, l.rcvkey, l.rcvSId, l.rcvIndex FROM ziduri as zu LEFT JOIN zrtp as z ON z.zuid=zu.zuid LEFT JOIN lime as l ON z.zuid=l.zuid WHERE zu.selfuri=? AND zu.peeruri=? AND zu.zid=? AND z.pvs=? LIMIT 1;"); + ret = sqlite3_prepare_v2(db, stmt, -1, &sqlStmt, NULL); + sqlite3_free(stmt); + if (ret != SQLITE_OK) { + return LIME_INVALID_CACHE; } + sqlite3_bind_text(sqlStmt, 1, selfURI,-1, SQLITE_TRANSIENT); + sqlite3_bind_text(sqlStmt, 2, peerURI,-1, SQLITE_TRANSIENT); + sqlite3_bind_blob(sqlStmt, 3, associatedKey->peerZID, 12, SQLITE_TRANSIENT); + sqlite3_bind_blob(sqlStmt, 4, pvsOne, 1, SQLITE_TRANSIENT); - while (cur!=NULL) { /* loop on all peer nodes */ - if ((!xmlStrcmp(cur->name, (const xmlChar *)"peer"))){ /* found a peer, check his ZID element */ - xmlChar *currentZidHex = xmlNodeListGetString(cacheBuffer, cur->xmlChildrenNode->xmlChildrenNode, 1); /* ZID is the first element of peer */ - if (!xmlStrcmp(currentZidHex, (const xmlChar *)peerZidHex)) { /* we found the peer element we are looking for */ - xmlNodePtr peerNodeChildren = cur->xmlChildrenNode->next; - while (peerNodeChildren != NULL && itemFound<4) { /* look for the tag we want to read : rcvKey, rcvSId, rcvIndex and pvs*/ - xmlChar *nodeContent = NULL; - if (!xmlStrcmp(peerNodeChildren->name, (const xmlChar *)"rcvKey")) { - nodeContent = xmlNodeListGetString(cacheBuffer, peerNodeChildren->xmlChildrenNode, 1); - bctbx_strToUint8(associatedKey->key, nodeContent, 64); - itemFound++; - } - if (!xmlStrcmp(peerNodeChildren->name, (const xmlChar *)"rcvSId")) { - nodeContent = xmlNodeListGetString(cacheBuffer, peerNodeChildren->xmlChildrenNode, 1); - bctbx_strToUint8(associatedKey->sessionId, nodeContent, 64); - itemFound++; - } - if (!xmlStrcmp(peerNodeChildren->name, (const xmlChar *)"rcvIndex")) { - uint8_t sessionIndexBuffer[4]; /* session index is a uint32_t but we first retrieved it as an hexa string, convert it to a 4 uint8_t buffer */ - nodeContent = xmlNodeListGetString(cacheBuffer, peerNodeChildren->xmlChildrenNode, 1); - bctbx_strToUint8(sessionIndexBuffer, nodeContent, 8); - /* convert it back to a uint32_t (MSByte first)*/ - associatedKey->sessionIndex = sessionIndexBuffer[3] + (sessionIndexBuffer[2]<<8) + (sessionIndexBuffer[1]<<16) + (sessionIndexBuffer[0]<<24); - itemFound++; - } - if (!xmlStrcmp(peerNodeChildren->name, (const xmlChar *)"pvs")) { - nodeContent = xmlNodeListGetString(cacheBuffer, peerNodeChildren->xmlChildrenNode, 1); - bctbx_strToUint8(&pvs, nodeContent, 2); /* pvs is retrieved as a 2 characters hexa string, convert it to an int8 */ - itemFound++; - } - xmlFree(nodeContent); - peerNodeChildren = peerNodeChildren->next; - } - xmlFree(currentZidHex); - break; /* we parsed the peer node we were looking for, get out of the main while */ - } - xmlFree(currentZidHex); + + if ((ret = sqlite3_step(sqlStmt)) == SQLITE_ROW) { /* we found a row */ + /* get zuid from column 0 */ + associatedKey->zuid = sqlite3_column_int(sqlStmt, 0); + + /* retrieve values : rcvKey, rcvSId, rcvIndex from columns 1,2,3 */ + length = sqlite3_column_bytes(sqlStmt, 1); + if (length==32) { /* rcvKey */ + memcpy(associatedKey->key, sqlite3_column_blob(sqlStmt, 1), length); + } else { /* something wrong */ + sqlite3_finalize(sqlStmt); + return LIME_NO_VALID_KEY_FOUND_FOR_PEER; } - cur = cur->next; - } - /* if we manage to find the correct key information and that pvs is set to 1, return 0 (success) */ - if ((pvs == 1) && (itemFound == 4)) { + length = sqlite3_column_bytes(sqlStmt, 2); + if (length==32) { /* rcvSId */ + memcpy(associatedKey->sessionId, sqlite3_column_blob(sqlStmt, 2), length); + } else { /* something wrong */ + sqlite3_finalize(sqlStmt); + return LIME_NO_VALID_KEY_FOUND_FOR_PEER; + } + + length = sqlite3_column_bytes(sqlStmt, 3); + if (length==4) { /* rcvKey */ + uint8_t *sessionId = (uint8_t *)sqlite3_column_blob(sqlStmt, 3); + associatedKey->sessionIndex = ((uint32_t)(sessionId[0]))<<24 | + ((uint32_t)(sessionId[1]))<<16 | + ((uint32_t)(sessionId[2]))<<8 | + ((uint32_t)(sessionId[3])); + } else { /* something wrong */ + sqlite3_finalize(sqlStmt); + return LIME_NO_VALID_KEY_FOUND_FOR_PEER; + } + + sqlite3_finalize(sqlStmt); return 0; } - /* otherwise, key wasn't found or is invalid */ - return LIME_NO_VALID_KEY_FOUND_FOR_PEER; -} - -int lime_setCachedKey(xmlDocPtr cacheBuffer, limeKey_t *associatedKey, uint8_t role, uint64_t validityTimeSpan) { - uint8_t done=0; - xmlNodePtr cur; - uint8_t peerZidHex[25]; - uint8_t keyHex[65]; /* key is 32 bytes long -> 64 bytes string + null termination */ - uint8_t sessionIdHex[65]; /* sessionId is 32 bytes long -> 64 bytes string + null termination */ - uint8_t sessionIndexHex[9]; /* sessionInedx is an uint32_t : 4 bytes long -> 8 bytes string + null termination */ - uint8_t validHex[17]; /* validity is a unix period in seconds on 64bits -> 16 bytes string + null termination */ - bctoolboxTimeSpec currentTimeSpec; - - uint8_t itemFound = 0; - - if (cacheBuffer == NULL ) { /* there is no cache return error */ + /* something is wrong with the cache? */ + if (ret!=SQLITE_DONE) { return LIME_INVALID_CACHE; } - /* get the given ZID into hex format */ - bctbx_int8ToStr(peerZidHex, associatedKey->peerZID, 12); - peerZidHex[24]='\0'; /* must be a null terminated string */ + /* reach here if the query executed correctly but returned no result */ + return LIME_NO_VALID_KEY_FOUND_FOR_PEER; +} - cur = xmlDocGetRootElement(cacheBuffer); - /* if we found a root element, parse its children node */ - if (cur!=NULL) - { - cur = cur->xmlChildrenNode; +int lime_setCachedKey(void *cachedb, limeKey_t *associatedKey, uint8_t role, uint64_t validityTimeSpan) { + bctoolboxTimeSpec currentTime; + /* columns to be written in cache */ + char *colNamesSender[] = {"sndKey", "sndSId", "sndIndex"}; /* Sender never update the validity period */ + char *colNamesReceiver[] = {"rcvKey", "rcvSId", "rcvIndex", "valid"}; + uint8_t *colValues[4]; + uint8_t sessionIndex[4]; /* buffer to hold the uint32_t buffer index in big endian */ + size_t colLength[] = {32, 32, 4, 8}; /* data length: keys and session ID : 32 bytes, Index: 4 bytes(uint32_t), validity : 8 bytes(UTC time as int64_t) */ + int colNums; + if (cachedb == NULL || associatedKey == NULL) { /* there is no cache return error */ + return LIME_INVALID_CACHE; } - /* convert the given tag content to null terminated Hexadecimal strings */ - bctbx_int8ToStr(keyHex, associatedKey->key, 32); - keyHex[64] = '\0'; - bctbx_int8ToStr(sessionIdHex, associatedKey->sessionId, 32); - sessionIdHex[64] = '\0'; - bctbx_uint32ToStr(sessionIndexHex, associatedKey->sessionIndex); + /* wrap values to be written */ + sessionIndex[0] = (associatedKey->sessionIndex>>24)&0xFF; + sessionIndex[1] = (associatedKey->sessionIndex>>16)&0xFF; + sessionIndex[2] = (associatedKey->sessionIndex>>8)&0xFF; + sessionIndex[3] = (associatedKey->sessionIndex)&0xFF; + colValues[0] = associatedKey->key; + colValues[1] = associatedKey->sessionId; + colValues[2] = sessionIndex; + + /* shall we update valid column? Enforce only when receiver, if timeSpan is 0, just ignore */ if (validityTimeSpan > 0 && role == LIME_RECEIVER) { - bctbx_get_utc_cur_time(¤tTimeSpec); - bctbx_timespec_add(¤tTimeSpec, validityTimeSpan); - bctbx_uint64ToStr(validHex, currentTimeSpec.tv_sec); + bctbx_get_utc_cur_time(¤tTime); + bctbx_timespec_add(¤tTime, validityTimeSpan); + /* store the int64_t in big endian in the cache(cache is not typed, all data seen as blob) */ + colValues[3][0] = (currentTime.tv_sec>>56)&0xFF; + colValues[3][1] = (currentTime.tv_sec>>48)&0xFF; + colValues[3][2] = (currentTime.tv_sec>>40)&0xFF; + colValues[3][3] = (currentTime.tv_sec>>32)&0xFF; + colValues[3][4] = (currentTime.tv_sec>>24)&0xFF; + colValues[3][5] = (currentTime.tv_sec>>16)&0xFF; + colValues[3][6] = (currentTime.tv_sec>>8)&0xFF; + colValues[3][7] = (currentTime.tv_sec)&0xFF; + + colNums = 4; + } else { + colNums = 3; /* do not write the valid column*/ } - while (cur!=NULL && done==0) { /* loop on all peer nodes */ - if ((!xmlStrcmp(cur->name, (const xmlChar *)"peer"))){ /* found a peer, check his ZID element */ - xmlChar *currentZidHex = xmlNodeListGetString(cacheBuffer, cur->xmlChildrenNode->xmlChildrenNode, 1); /* ZID is the first element of peer */ - if (!xmlStrcmp(currentZidHex, (const xmlChar *)peerZidHex)) { /* we found the peer element we are looking for */ - uint8_t validFound = 0; - xmlNodePtr peerNodeChildren = cur->xmlChildrenNode->next; - if (role==LIME_SENDER) { - itemFound=1; /* we do not look for valid when setting sender key */ - } - while (peerNodeChildren != NULL && itemFound<4) { /* look for the tag we want to write */ - if (role == LIME_RECEIVER) { /* writing receiver key */ - if (!xmlStrcmp(peerNodeChildren->name, (const xmlChar *)"rcvKey")) { - xmlNodeSetContent(peerNodeChildren, (const xmlChar *)keyHex); - itemFound++; - } - if (!xmlStrcmp(peerNodeChildren->name, (const xmlChar *)"rcvSId")) { - xmlNodeSetContent(peerNodeChildren, (const xmlChar *)sessionIdHex); - itemFound++; - } - if (!xmlStrcmp(peerNodeChildren->name, (const xmlChar *)"rcvIndex")) { - xmlNodeSetContent(peerNodeChildren, (const xmlChar *)sessionIndexHex); - itemFound++; - } - if (!xmlStrcmp(peerNodeChildren->name, (const xmlChar *)"valid")) { - if (validityTimeSpan > 0) { - xmlNodeSetContent(peerNodeChildren, (const xmlChar *)validHex); - } - itemFound++; - validFound=1; - } - } else { /* writing sender key */ - if (!xmlStrcmp(peerNodeChildren->name, (const xmlChar *)"sndKey")) { - xmlNodeSetContent(peerNodeChildren, (const xmlChar *)keyHex); - itemFound++; - } - if (!xmlStrcmp(peerNodeChildren->name, (const xmlChar *)"sndSId")) { - xmlNodeSetContent(peerNodeChildren, (const xmlChar *)sessionIdHex); - itemFound++; - } - if (!xmlStrcmp(peerNodeChildren->name, (const xmlChar *)"sndIndex")) { - xmlNodeSetContent(peerNodeChildren, (const xmlChar *)sessionIndexHex); - itemFound++; - } - } - peerNodeChildren = peerNodeChildren->next; - } - - /* we may want to add the valid node which if it is missing and we've been ask to update it */ - if (role == LIME_RECEIVER && validityTimeSpan>0 && validFound==0) { - xmlNewTextChild(cur, NULL, (const xmlChar *)"valid", validHex); - } - done=1; /* step out of the loop */ - } - xmlFree(currentZidHex); - } - cur = cur->next; - } - return 0; + /* update cache */ + return bzrtp_cache_write(cachedb, associatedKey->zuid, "lime", role==LIME_SENDER?colNamesSender:colNamesReceiver, colValues, colLength, colNums); } /** @@ -442,11 +357,13 @@ void lime_freeKeys(limeURIKeys_t *associatedKeys) { } } - free(associatedKeys->peerKeys); + bctbx_free(associatedKeys->peerKeys); associatedKeys->peerKeys = NULL; - /* free sipURI string */ - free(associatedKeys->peerURI); + /* free sipURI strings */ + bctbx_free(associatedKeys->selfURI); + associatedKeys->selfURI = NULL; + bctbx_free(associatedKeys->peerURI); associatedKeys->peerURI = NULL; } @@ -542,7 +459,7 @@ int lime_decryptMessage(limeKey_t *key, uint8_t *encryptedMessage, uint32_t mess return retval; } -int lime_createMultipartMessage(xmlDocPtr cacheBuffer, const char *contentType, uint8_t *message, uint8_t *peerURI, uint8_t **output) { +int lime_createMultipartMessage(void *cachedb, const char *contentType, uint8_t *message, const char *selfURI, const char *peerURI, uint8_t **output) { uint8_t selfZidHex[25]; uint8_t selfZid[12]; /* same data but in byte buffer */ uint32_t encryptedMessageLength; @@ -554,23 +471,22 @@ int lime_createMultipartMessage(xmlDocPtr cacheBuffer, const char *contentType, int xmlStringLength; xmlChar *local_output = NULL; - /* retrieve selfZIDHex from cache(return a 24 char hexa string + null termination) */ - if (lime_getSelfZid(cacheBuffer, selfZidHex) != 0) { + /* retrieve selfZIDHex from cache */ + if (bzrtp_getSelfZID(cachedb, selfURI, selfZid, NULL) != 0) { return LIME_UNABLE_TO_ENCRYPT_MESSAGE; } - bctbx_strToUint8(selfZid, selfZidHex, 24); /* encrypted message length is plaintext + 16 for tag */ encryptedMessageLength = (uint32_t)strlen((char *)message) + 16; encryptedContentTypeLength = (uint32_t)strlen((char *)contentType) + 16; /* retrieve keys associated to the peer URI */ - associatedKeys.peerURI = (uint8_t *)malloc(strlen((char *)peerURI)+1); - strcpy((char *)(associatedKeys.peerURI), (char *)peerURI); + associatedKeys.peerURI = bctbx_strdup(peerURI); + associatedKeys.selfURI = bctbx_strdup(selfURI); associatedKeys.associatedZIDNumber = 0; associatedKeys.peerKeys = NULL; - if ((ret = lime_getCachedSndKeysByURI(cacheBuffer, &associatedKeys)) != 0) { + if ((ret = lime_getCachedSndKeysByURI(cachedb, &associatedKeys)) != 0) { lime_freeKeys(&associatedKeys); return ret; } @@ -580,7 +496,9 @@ int lime_createMultipartMessage(xmlDocPtr cacheBuffer, const char *contentType, /* root tag is "doc" */ rootNode = xmlNewDocNode(xmlOutputMessage, NULL, (const xmlChar *)"doc", NULL); xmlDocSetRootElement(xmlOutputMessage, rootNode); - /* add the self ZID child */ + /* add the self ZID child, convert it to an hexa string */ + bctbx_int8ToStr(selfZidHex, selfZid, 12); + selfZidHex[24] = '\0'; /* add a NULL termination for libxml */ xmlNewTextChild(rootNode, NULL, (const xmlChar *)"ZID", selfZidHex); /* loop on all keys found */ @@ -638,7 +556,7 @@ int lime_createMultipartMessage(xmlDocPtr cacheBuffer, const char *contentType, /* update the key used */ lime_deriveKey(currentKey); - lime_setCachedKey(cacheBuffer, currentKey, LIME_SENDER, 0); /* never update validity when sending a message */ + lime_setCachedKey(cachedb, currentKey, LIME_SENDER, 0); /* never update validity when sending a message */ } /* dump the whole message doc into the output */ @@ -655,7 +573,7 @@ int lime_createMultipartMessage(xmlDocPtr cacheBuffer, const char *contentType, return 0; } -int lime_decryptMultipartMessage(xmlDocPtr cacheBuffer, uint8_t *message, uint8_t **output, char **content_type, uint64_t validityTimeSpan) { +int lime_decryptMultipartMessage(void *cachedb, uint8_t *message, const char *selfURI, const char *peerURI, uint8_t **output, char **content_type, uint64_t validityTimeSpan) { int retval = 0; uint8_t selfZidHex[25]; uint8_t selfZid[12]; /* same data but in byte buffer */ @@ -671,14 +589,16 @@ int lime_decryptMultipartMessage(xmlDocPtr cacheBuffer, uint8_t *message, uint8_ uint32_t usedSessionIndex = 0; int i; - if (cacheBuffer == NULL) { + if (cachedb == NULL) { return LIME_INVALID_CACHE; } - /* retrieve selfZIDHex from cache(return a 24 char hexa string + null termination) */ - if (lime_getSelfZid(cacheBuffer, selfZidHex) != 0) { + + /* retrieve selfZID from cache, and convert it to an Hexa buffer to easily match it against hex string containg in xml message as pzid */ + if (bzrtp_getSelfZID(cachedb, selfURI, selfZid, NULL) != 0) { return LIME_UNABLE_TO_DECRYPT_MESSAGE; } - bctbx_strToUint8(selfZid, selfZidHex, 24); + bctbx_int8ToStr(selfZidHex, selfZid, 12); + selfZidHex[24]='\0'; xml_ctx = linphone_xmlparsing_context_new(); xmlSetGenericErrorFunc(xml_ctx, linphone_xmlparsing_genericxml_error); @@ -701,12 +621,12 @@ int lime_decryptMultipartMessage(xmlDocPtr cacheBuffer, uint8_t *message, uint8_ linphone_free_xml_text_content(peerZidHex); /* Get the matching key from cache */ - retval = lime_getCachedRcvKeyByZid(cacheBuffer, &associatedKey); + retval = lime_getCachedRcvKeyByZid(cachedb, &associatedKey, selfURI, peerURI); if (retval != 0) { goto error; } - /* Retrieve the portion of message which is encrypted with our key */ + /* Retrieve the portion of message which is encrypted with our key(seek for a pzid matching our) */ msg_object = linphone_get_xml_xpath_object_for_node_list(xml_ctx, "/doc/msg"); if ((msg_object != NULL) && (msg_object->nodesetval != NULL)) { for (i = 1; i <= msg_object->nodesetval->nodeNr; i++) { @@ -793,7 +713,7 @@ int lime_decryptMultipartMessage(xmlDocPtr cacheBuffer, uint8_t *message, uint8_ /* update used key */ lime_deriveKey(&associatedKey); - lime_setCachedKey(cacheBuffer, &associatedKey, LIME_RECEIVER, validityTimeSpan); + lime_setCachedKey(cachedb, &associatedKey, LIME_RECEIVER, validityTimeSpan); error: linphone_xmlparsing_context_destroy(xml_ctx); @@ -806,40 +726,22 @@ bool_t linphone_chat_room_lime_available(LinphoneChatRoom *cr) { case LinphoneLimeDisabled: return FALSE; case LinphoneLimeMandatory: 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"); - return FALSE; - } - cacheString[cacheSize] = '\0'; - cacheSize += 1; - fclose(CACHEFD); - cacheXml = xmlParseDoc((xmlChar*)cacheString); - ms_free(cacheString); - if (cacheXml) { - bool_t res; - limeURIKeys_t associatedKeys; - char *peer = linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr)); + void *zrtp_cache_db = linphone_core_get_zrtp_cache_db(cr->lc); + if (zrtp_cache_db != NULL) { + bool_t res; + limeURIKeys_t associatedKeys; + char *peer = linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr)); - /* retrieve keys associated to the peer URI */ - associatedKeys.peerURI = (uint8_t *)malloc(strlen(peer)+1); - strcpy((char *)(associatedKeys.peerURI), peer); - associatedKeys.associatedZIDNumber = 0; - associatedKeys.peerKeys = NULL; - - res = (lime_getCachedSndKeysByURI(cacheXml, &associatedKeys) == 0); - lime_freeKeys(&associatedKeys); - xmlFreeDoc(cacheXml); - ms_free(peer); - return res; - } - } + /* retrieve keys associated to the peer URI */ + associatedKeys.peerURI = bctbx_strdup(peer); + associatedKeys.selfURI = NULL; /* TODO : there is no sender associated to chatroom so check for any local URI available, shall we add sender to chatroom? */ + associatedKeys.associatedZIDNumber = 0; + associatedKeys.peerKeys = NULL; + /* with NULL is selfURI, just retrieve keys for any local uri found in cache, shall we use a dedicated function which would + return the list of possible uris and store the selected one in the chatroom ? */ + res = (lime_getCachedSndKeysByURI(zrtp_cache_db, &associatedKeys) == 0); + lime_freeKeys(&associatedKeys); + return res; } } } @@ -852,70 +754,43 @@ int lime_im_encryption_engine_process_incoming_message_cb(LinphoneImEncryptionEn int errcode = -1; /* check if we have a xml/cipher message to be decrypted */ 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); errcode = 0; - if (zrtp_secrets_cache != NULL) CACHEFD = fopen(zrtp_secrets_cache, "rb+"); - if (CACHEFD == NULL) { - ms_warning("Unable to access ZRTP ZID cache to decrypt message"); + int retval; + void *zrtp_cache_db = NULL; /* use a void * instead of sqlite3 * to avoid problems and ifdef when SQLITE is not available(the get function shall return NULL in that case) */ + uint8_t *decrypted_body = NULL; + char *decrypted_content_type = NULL; + char *peerUri = NULL; + char *selfUri = NULL; + + zrtp_cache_db = linphone_core_get_zrtp_cache_db(lc); + if (zrtp_cache_db == NULL) { + ms_warning("Unable to load content of ZRTP ZID cache to decrypt message"); errcode = 500; return errcode; + } + peerUri = linphone_address_as_string_uri_only(msg->from); + selfUri = linphone_address_as_string_uri_only(msg->to); + retval = lime_decryptMultipartMessage(zrtp_cache_db, (uint8_t *)msg->message, selfUri, peerUri, &decrypted_body, &decrypted_content_type, bctbx_time_string_to_sec(lp_config_get_string(lc->config, "sip", "lime_key_validity", "0"))); + if (retval != 0) { + ms_warning("Unable to decrypt message, reason : %s", lime_error_code_to_string(retval)); + if (decrypted_body) ms_free(decrypted_body); + errcode = 488; + return errcode; } else { - size_t cacheSize; - char *cacheString; - int retval; - xmlDocPtr cacheXml; - uint8_t *decrypted_body = NULL; - char *decrypted_content_type = NULL; - - cacheString=ms_load_file_content(CACHEFD, &cacheSize); - if (!cacheString){ - ms_warning("Unable to load content of ZRTP ZID cache to decrypt message"); - errcode = 500; - return errcode; + /* swap encrypted message with plain text message */ + if (msg->message) { + ms_free(msg->message); } - cacheString[cacheSize] = '\0'; - cacheSize += 1; - fclose(CACHEFD); - cacheXml = xmlParseDoc((xmlChar*)cacheString); - ms_free(cacheString); - retval = lime_decryptMultipartMessage(cacheXml, (uint8_t *)msg->message, &decrypted_body, &decrypted_content_type, bctbx_time_string_to_sec(lp_config_get_string(lc->config, "sip", "lime_key_validity", "0"))); - if (retval != 0) { - ms_warning("Unable to decrypt message, reason : %s", lime_error_code_to_string(retval)); - if (decrypted_body) ms_free(decrypted_body); - xmlFreeDoc(cacheXml); - errcode = 488; - return errcode; + msg->message = (char *)decrypted_body; + if (decrypted_content_type != NULL) { + linphone_chat_message_set_content_type(msg, decrypted_content_type); } else { - /* dump updated cache to a string */ - xmlChar *xmlStringOutput; - int xmlStringLength; - xmlDocDumpFormatMemoryEnc(cacheXml, &xmlStringOutput, &xmlStringLength, "UTF-8", 0); - /* write it to the cache file */ - CACHEFD = fopen(zrtp_secrets_cache, "wb+"); - if (fwrite(xmlStringOutput, 1, xmlStringLength, CACHEFD)<=0){ - ms_warning("Fail to write cache"); - } - xmlFree(xmlStringOutput); - fclose(CACHEFD); - if (msg->message) { - ms_free(msg->message); - } - msg->message = (char *)decrypted_body; - - if (decrypted_content_type != NULL) { - linphone_chat_message_set_content_type(msg, decrypted_content_type); + if (strcmp("application/cipher.vnd.gsma.rcs-ft-http+xml", msg->content_type) == 0) { + linphone_chat_message_set_content_type(msg, "application/vnd.gsma.rcs-ft-http+xml"); } else { - if (strcmp("application/cipher.vnd.gsma.rcs-ft-http+xml", msg->content_type) == 0) { - linphone_chat_message_set_content_type(msg, "application/vnd.gsma.rcs-ft-http+xml"); - } else { - linphone_chat_message_set_content_type(msg, "text/plain"); - } + linphone_chat_message_set_content_type(msg, "text/plain"); } } - - xmlFreeDoc(cacheXml); } } return errcode; @@ -927,6 +802,7 @@ int lime_im_encryption_engine_process_outgoing_message_cb(LinphoneImEncryptionEn char *new_content_type = "xml/cipher"; if(linphone_core_lime_enabled(room->lc)) { if (linphone_chat_room_lime_available(room)) { + void *zrtp_cache_db = NULL; /* use a void * instead of sqlite3 * to avoid problems and ifdef when SQLITE is not available(the get function shall return NULL in that case) */ if (msg->content_type) { 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 @@ -941,56 +817,31 @@ int lime_im_encryption_engine_process_outgoing_message_cb(LinphoneImEncryptionEn } /* 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+"); + zrtp_cache_db = linphone_core_get_zrtp_cache_db(lc); errcode = 0; - if (CACHEFD == NULL) { + if (zrtp_cache_db == NULL) { ms_warning("Unable to access ZRTP ZID cache to encrypt message"); errcode = 488; } else { - size_t cacheSize; - 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)); + char *selfUri = linphone_address_as_string_uri_only(msg->from); + char *peerUri = linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(room)); - cacheString=ms_load_file_content(CACHEFD, &cacheSize); - if (!cacheString){ - ms_warning("Unable to load content of ZRTP ZID cache to encrypt message"); - errcode = 500; - return errcode; - } - cacheString[cacheSize] = '\0'; - cacheSize += 1; - fclose(CACHEFD); - cacheXml = xmlParseDoc((xmlChar*)cacheString); - ms_free(cacheString); - retval = lime_createMultipartMessage(cacheXml, msg->content_type, (uint8_t *)msg->message, (uint8_t *)peer, &crypted_body); - if (retval != 0) { - ms_warning("Unable to encrypt message for %s : %s", peer, lime_error_code_to_string(retval)); + retval = lime_createMultipartMessage(zrtp_cache_db, msg->content_type, (uint8_t *)msg->message, selfUri, peerUri, &crypted_body); + if (retval != 0) { /* fail to encrypt */ + ms_warning("Unable to encrypt message for %s : %s", room->peer, lime_error_code_to_string(retval)); if (crypted_body) ms_free(crypted_body); errcode = 488; - } else { - /* dump updated cache to a string */ - xmlChar *xmlStringOutput; - int xmlStringLength; - xmlDocDumpFormatMemoryEnc(cacheXml, &xmlStringOutput, &xmlStringLength, "UTF-8", 0); - /* write it to the cache file */ - CACHEFD = fopen(zrtp_secrets_cache, "wb+"); - if (fwrite(xmlStringOutput, 1, xmlStringLength, CACHEFD)<=0){ - ms_warning("Unable to write zid cache"); - } - xmlFree(xmlStringOutput); - fclose(CACHEFD); + } else { /* encryption ok, swap plain text message body by encrypted one */ if (msg->message) { ms_free(msg->message); } msg->message = (char *)crypted_body; msg->content_type = ms_strdup(new_content_type); } - ms_free(peer); - xmlFreeDoc(cacheXml); + ms_free(peerUri); + ms_free(selfUri); } } else { if (linphone_core_lime_enabled(lc) == LinphoneLimeMandatory) { @@ -1050,12 +901,12 @@ void lime_im_encryption_engine_generate_file_transfer_key_cb(LinphoneImEncryptio bool_t lime_is_available() { return FALSE; } int lime_decryptFile(void **cryptoContext, unsigned char *key, size_t length, char *plain, char *cipher) { return LIME_NOT_ENABLED;} -int lime_decryptMultipartMessage(xmlDocPtr cacheBuffer, uint8_t *message, uint8_t **output, char **content_type, uint64_t validityTimeSpan) { return LIME_NOT_ENABLED;} -int lime_createMultipartMessage(xmlDocPtr cacheBuffer, const char *content_type, uint8_t *message, uint8_t *peerURI, uint8_t **output) { return LIME_NOT_ENABLED;} +int lime_decryptMultipartMessage(void *cachedb, uint8_t *message, const char *selfURI, const char *peerURI, uint8_t **output, char **content_type, uint64_t validityTimeSpan) { return LIME_NOT_ENABLED;} +int lime_createMultipartMessage(void *cachedb, const char *contentType, uint8_t *message, const char *selfURI, const char *peerURI, uint8_t **output) { return LIME_NOT_ENABLED;} int lime_encryptFile(void **cryptoContext, unsigned char *key, size_t length, char *plain, char *cipher) {return LIME_NOT_ENABLED;} void lime_freeKeys(limeURIKeys_t *associatedKeys){ } -int lime_getCachedSndKeysByURI(xmlDocPtr cacheBuffer, limeURIKeys_t *associatedKeys){ +int lime_getCachedSndKeysByURI(void *cachedb, limeURIKeys_t *associatedKeys){ return LIME_NOT_ENABLED; } int lime_encryptMessage(limeKey_t *key, const uint8_t *plainMessage, uint32_t messageLength, uint8_t selfZID[12], uint8_t *encryptedMessage) { @@ -1064,7 +915,7 @@ int lime_encryptMessage(limeKey_t *key, const uint8_t *plainMessage, uint32_t me int lime_setCachedKey(xmlDocPtr cacheBuffer, limeKey_t *associatedKey, uint8_t role, uint64_t validityTimeSpan) { return LIME_NOT_ENABLED; } -int lime_getCachedRcvKeyByZid(xmlDocPtr cacheBuffer, limeKey_t *associatedKey) { +int lime_getCachedRcvKeyByZid(xmlDocPtr cacheBuffer, limeKey_t *associatedKey, const char *selfURI, const char *peerURI) { return LIME_NOT_ENABLED; } int lime_decryptMessage(limeKey_t *key, uint8_t *encryptedMessage, uint32_t messageLength, uint8_t selfZID[12], uint8_t *plainMessage) { diff --git a/coreapi/lime.h b/coreapi/lime.h index 67753c038..cae4799e9 100644 --- a/coreapi/lime.h +++ b/coreapi/lime.h @@ -45,6 +45,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. /** * @brief Structure holding all needed material to encrypt/decrypt Messages */ typedef struct limeKey_struct { + int zuid; /**< the internal cache id for this key, zuid is a binding on local uri and zid <-> peer uri and zid */ uint8_t key[32]; /**< a 256 bit key used to encrypt/decrypt message */ uint8_t sessionId[32]; /**< a session id used to derive key */ uint32_t sessionIndex; /**< an index to count number of derivation */ @@ -56,7 +57,8 @@ typedef struct limeKey_struct { typedef struct limeURIKeys_struct { limeKey_t **peerKeys; /**< an array of all the key material associated to each ZID matching the specified URI */ uint16_t associatedZIDNumber; /**< previous array length */ - uint8_t *peerURI; /**< the sip URI associated to all the keys, must be a null terminated string */ + char *peerURI; /**< the peer sip URI associated to all the keys, must be a null terminated string */ + char *selfURI; /**< the local sip URI used to send messages, must be a null terminated string */ } limeURIKeys_t; /** @@ -64,35 +66,36 @@ typedef struct limeURIKeys_struct { * peerKeys field from associatedKeys param must be NULL when calling this function. * Structure content must then be freed using lime_freeKeys function * - * @param[in] cacheBuffer The xmlDoc containing current cache - * @param[in,out] associatedKeys Structure containing the peerURI. After this call contains all key material associated to the given URI. Must be then freed through lime_freeKeys function + * @param[in] cachedb Pointer to the sqlite3 DB + * @param[in,out] associatedKeys Structure containing the self and peer URI. After this call contains all key material associated to the given URI. Must be then freed through lime_freeKeys function * * @return 0 on success(at least one valid key found), error code otherwise */ -LINPHONE_PUBLIC int lime_getCachedSndKeysByURI(xmlDocPtr cacheBuffer, limeURIKeys_t *associatedKeys); +LINPHONE_PUBLIC int lime_getCachedSndKeysByURI(void *cachedb, limeURIKeys_t *associatedKeys); /** * @brief Get the receiver key associated to the ZID given in the associatedKey parameter * - * @param[in] cacheBuffer The xmlDoc containing current cache - * @param[in,out] associatedKey Structure containing the peerZID and will store the retrieved key + * @param[in] cachedb Pointer to the sqlite3 DB + * @param[in,out] associatedKey Structure containing the peerZID and will store the retrieved key + * @param[in] selfURI The source URI + * @param[in] peerURI The destination URI * * @return 0 on success, error code otherwise */ -LINPHONE_PUBLIC int lime_getCachedRcvKeyByZid(xmlDocPtr cacheBuffer, limeKey_t *associatedKey); +LINPHONE_PUBLIC int lime_getCachedRcvKeyByZid(void *cachedb, limeKey_t *associatedKey, const char *selfURI, const char *peerURI); /** * @brief Set in cache the given key material, association is made by ZID contained in the associatedKey parameter * - * @param[out] cacheBuffer The xmlDoc containing current cache to be updated + * @param[in/out] cachedb Pointer to the sqlite3 DB * @param[in,out] associatedKey Structure containing the key and ZID to identify the peer node to be updated * @param[in] role Can be LIME_SENDER or LIME_RECEIVER, specify which key we want to update * @param[in] validityTimeSpan If not 0, set the tag to now+validityTimeSpan (in seconds) * * @return 0 on success, error code otherwise */ - -LINPHONE_PUBLIC int lime_setCachedKey(xmlDocPtr cacheBuffer, limeKey_t *associatedKey, uint8_t role, uint64_t validityTimeSpan); +LINPHONE_PUBLIC int lime_setCachedKey(void *cachedb, limeKey_t *associatedKey, uint8_t role, uint64_t validityTimeSpan); /** * @brief Free all allocated data in the associated keys structure @@ -167,28 +170,31 @@ LINPHONE_PUBLIC int lime_decryptMessage(limeKey_t *key, uint8_t *encryptedMessag * @brief create the encrypted multipart xml message from plain text and destination URI * Retrieve in cache the needed keys which are then updated. Output buffer is allocated and must be freed by caller * - * @param[in,out] cacheBuffer The xmlDoc containing current cache, get the keys and selfZID from it, updated by this function with derivated keys - * @param[in] content_type The content type of the message to encrypt + * @param[in,out] cachedb Pointer to the sqlite DB holding zrtp/lime cache, get the keys and selfZID from it, updated by this function with derivated keys + * @param[in] content_type The content type of the message to encrypt * @param[in] message The message content to be encrypted + * @param[in] selfURI The source URI * @param[in] peerURI The destination URI, associated keys will be found in cache * @param[out] output The output buffer, allocated and set with the encrypted message xml body(null terminated string). Must be freed by caller * * @return 0 on success, error code otherwise */ -LINPHONE_PUBLIC int lime_createMultipartMessage(xmlDocPtr cacheBuffer, const char *content_type, uint8_t *message, uint8_t *peerURI, uint8_t **output); +LINPHONE_PUBLIC int lime_createMultipartMessage(void *cachedb, const char *contentType, uint8_t *message, const char *selfURI, const char *peerURI, uint8_t **output); /** * @brief decrypt a multipart xml message * Retrieve in cache the needed key which is then updated. Output buffer is allocated and must be freed by caller * - * @param[in,out] cacheBuffer The xmlDoc containing current cache, get the key and selfZID from it, updated by this function with derivated keys + * @param[in,out] cachedb Pointer to the sqlite DB holding zrtp/lime cache, get the keys and selfZID from it, updated by this function with derivated keys * @param[in] message The multipart message, contain one or several part identified by destination ZID, one shall match the self ZID retrieved from cache + * @param[in] selfURI The source URI + * @param[in] peerURI The destination URI, associated keys will be found in cache * @param[out] output The output buffer, allocated and set with the decrypted message(null terminated string). Must be freed by caller * @param[out] content_type The content type of the decrypted message * @param[in] validityTimeSpan If not 0, update the tag associated to sender to now+validityTimeSpan (in seconds) * @return 0 on success, error code otherwise */ -LINPHONE_PUBLIC int lime_decryptMultipartMessage(xmlDocPtr cacheBuffer, uint8_t *message, uint8_t **output, char **content_type, uint64_t validityTimeSpan); +LINPHONE_PUBLIC int lime_decryptMultipartMessage(void *cachedb, uint8_t *message, const char *selfURI, const char *peerURI, uint8_t **output, char **content_type, uint64_t validityTimeSpan); /** * @brief given a readable version of error code generated by Lime functions diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index b3d7a4c80..c7cb6d341 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -2608,16 +2608,19 @@ void linphone_call_init_audio_stream(LinphoneCall *call){ /* init zrtp even if we didn't explicitely set it, just in case peer offers it */ if (linphone_core_media_encryption_supported(lc, LinphoneMediaEncryptionZRTP)) { - char *uri = linphone_address_as_string_uri_only((call->dir==LinphoneCallIncoming) ? call->log->from : call->log->to); + char *peerUri = linphone_address_as_string_uri_only((call->dir==LinphoneCallIncoming) ? call->log->from : call->log->to); + char *selfUri = linphone_address_as_string_uri_only((call->dir==LinphoneCallIncoming) ? call->log->to : call->log->from); MSZrtpParams params; memset(¶ms,0,sizeof(MSZrtpParams)); /*call->current_params.media_encryption will be set later when zrtp is activated*/ - params.zid_file=lc->zrtp_secrets_cache; - params.uri=uri; + params.zidCacheDB = linphone_core_get_zrtp_cache_db(lc); + params.peerUri=peerUri; + params.selfUri=selfUri; params.limeKeyTimeSpan = bctbx_time_string_to_sec(lp_config_get_string(lc->config, "sip", "lime_key_validity", "0")); /* get key lifespan from config file, default is 0:forever valid */ setZrtpCryptoTypesParameters(¶ms,call->core); audio_stream_enable_zrtp(call->audiostream,¶ms); - if (uri != NULL) ms_free(uri); + if (peerUri != NULL) ms_free(peerUri); + if (selfUri != NULL) ms_free(selfUri); } media_stream_reclaim_sessions(&audiostream->ms, &call->sessions[call->main_audio_stream_index]); diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 9fe02609f..8c60c9b3f 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -28,6 +28,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #ifdef SQLITE_STORAGE_ENABLED #include "sqlite3_bctbx_vfs.h" +/* we need bzrtp.h to setup the zrtp cache only when SQLITE is enabled */ +#include "bzrtp/bzrtp.h" #endif #include @@ -104,6 +106,7 @@ static void set_sip_network_reachable(LinphoneCore* lc,bool_t isReachable, time_ static void set_media_network_reachable(LinphoneCore* lc,bool_t isReachable); static void linphone_core_run_hooks(LinphoneCore *lc); static void linphone_core_uninit(LinphoneCore *lc); +static void linphone_core_zrtp_cache_close(LinphoneCore *lc); #include "enum.h" #include "contact_providers_priv.h" @@ -5739,6 +5742,11 @@ static void linphone_core_uninit(LinphoneCore *lc) if(lc->zrtp_secrets_cache != NULL) { ms_free(lc->zrtp_secrets_cache); } + + if(lc->zrtp_cache_db_file != NULL) { + ms_free(lc->zrtp_cache_db_file); + } + if(lc->user_certificates_path != NULL) { ms_free(lc->user_certificates_path); } @@ -5772,6 +5780,7 @@ static void linphone_core_uninit(LinphoneCore *lc) linphone_core_message_storage_close(lc); linphone_core_call_log_storage_close(lc); linphone_core_friends_storage_close(lc); + linphone_core_zrtp_cache_close(lc); linphone_core_set_state(lc,LinphoneGlobalOff,"Off"); linphone_core_deactivate_log_serialization_if_needed(); @@ -6159,6 +6168,72 @@ const char *linphone_core_get_zrtp_secrets_file(LinphoneCore *lc){ return lc->zrtp_secrets_cache; } +void *linphone_core_get_zrtp_cache_db(LinphoneCore *lc){ +#ifdef SQLITE_STORAGE_ENABLED + return (void *)lc->zrtp_cache_db; +#else /* SQLITE_STORAGE_ENABLED */ + return NULL; +#endif /* SQLITE_STORAGE_ENABLED */ +} + +static void linphone_core_zrtp_cache_close(LinphoneCore *lc) { +#ifdef SQLITE_STORAGE_ENABLED + if (lc->zrtp_cache_db) { + sqlite3_close(lc->zrtp_cache_db); + lc->zrtp_cache_db = NULL; + } +#endif /* SQLITE_STORAGE_ENABLED */ +} + +#ifdef SQLITE_STORAGE_ENABLED +static void linphone_core_zrtp_cache_db_init(LinphoneCore *lc) { + int ret; + const char *errmsg; + sqlite3 *db; + + linphone_core_zrtp_cache_close(lc); + + ret = _linphone_sqlite3_open(lc->zrtp_cache_db_file, &db); + if (ret != SQLITE_OK) { + errmsg = sqlite3_errmsg(db); + ms_error("Error in the opening zrtp_cache_db_file(%s): %s.\n", lc->zrtp_cache_db_file, errmsg); + sqlite3_close(db); + lc->zrtp_cache_db=NULL; + return; + } + + ret = bzrtp_initCache((void *)db); /* this may perform an update, check return value */ + + if (ret == BZRTP_CACHE_SETUP || ret == BZRTP_CACHE_UPDATE) { + /* After updating schema, database need to be closed/reopenned */ + sqlite3_close(db); + _linphone_sqlite3_open(lc->zrtp_cache_db_file, &db); + } + + if (ret == BZRTP_CACHE_SETUP && lc->zrtp_secrets_cache != NULL) { + /* we just created the db and we have an old XML version of the cache : migrate */ + /* TODO */ + } + + lc->zrtp_cache_db = db; +} +#else /* SQLITE_STORAGE_ENABLED */ +static void linphone_core_zrtp_cache_db_init(LinphoneCore *lc) { + ms_warning("Tried to open %s as zrtp_cache_db_file, but SQLITE_STORAGE is not enabled", lc->zrtp_cache_db_file); +} +#endif /* SQLITE_STORAGE_ENABLED */ + +void linphone_core_set_zrtp_cache_database_path(LinphoneCore *lc, const char *path) { + if (lc->zrtp_cache_db_file){ + ms_free(lc->zrtp_cache_db_file); + lc->zrtp_cache_db_file = NULL; + } + if (path) { + lc->zrtp_cache_db_file = ms_strdup(path); + linphone_core_zrtp_cache_db_init(lc); + } +} + void linphone_core_set_user_certificates_path(LinphoneCore *lc, const char* path){ char* new_value; new_value = path?ms_strdup(path):NULL; diff --git a/coreapi/private.h b/coreapi/private.h index ae74b85ef..0de7b7261 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -1053,7 +1053,7 @@ struct _LinphoneCore struct _EchoTester *ect; LinphoneTaskList hooks; /*tasks periodically executed in linphone_core_iterate()*/ LinphoneConference *conf_ctx; - char* zrtp_secrets_cache; + char* zrtp_secrets_cache; /**< zrtp xml filename cache : obsolete, use zrtp_cache_db now, kept to allow cache migration */ char* user_certificates_path; LinphoneVideoPolicy video_policy; time_t network_last_check; @@ -1088,7 +1088,9 @@ struct _LinphoneCore char *chat_db_file; char *logs_db_file; char *friends_db_file; + char *zrtp_cache_db_file; #ifdef SQLITE_STORAGE_ENABLED + sqlite3 *zrtp_cache_db; /**< zrtp sqlite cache, used by both zrtp and lime */ sqlite3 *db; sqlite3 *logs_db; sqlite3 *friends_db; diff --git a/gtk/main.c b/gtk/main.c index 8d12ac9ee..394657281 100644 --- a/gtk/main.c +++ b/gtk/main.c @@ -253,7 +253,8 @@ gboolean linphone_gtk_get_audio_assistant_option(void){ static void linphone_gtk_init_liblinphone(const char *config_file, const char *factory_config_file, const char *chat_messages_db_file, - const char *call_logs_db_file, const char *friends_db_file) { + const char *call_logs_db_file, const char *friends_db_file, + const char *zrtp_cache_db_file) { LinphoneCoreVTable vtable={0}; gchar *secrets_file=linphone_gtk_get_config_file(SECRETS_FILE); gchar *user_certificates_dir=linphone_gtk_get_config_file(CERTIFICATES_PATH); @@ -289,7 +290,8 @@ static void linphone_gtk_init_liblinphone(const char *config_file, linphone_core_set_user_agent(the_core,"Linphone", LINPHONE_VERSION); linphone_core_set_waiting_callback(the_core,linphone_gtk_wait,NULL); - linphone_core_set_zrtp_secrets_file(the_core,secrets_file); + linphone_core_set_zrtp_secrets_file(the_core,secrets_file); /* XML cache is superseeded by the sqlite one, keep it for migration purpose but it shall be removed in future version */ + if (zrtp_cache_db_file) linphone_core_set_zrtp_cache_database_path(the_core, zrtp_cache_db_file); g_free(secrets_file); linphone_core_set_user_certificates_path(the_core,user_certificates_dir); g_free(user_certificates_dir); @@ -2153,6 +2155,33 @@ static void populate_xdg_data_dirs_envvar(void) { g_strfreev(paths); #endif } +#define ZRTP_CACHE_CONFIG_FILE ".linphone-zidcache.db" + +static char *linphone_gtk_zrtp_cache_get_db_file(const char *filename){ + const int path_max=1024; + char *db_file=NULL; + + db_file=(char *)g_malloc(path_max*sizeof(char)); + if (filename==NULL) filename=ZRTP_CACHE_CONFIG_FILE; + /*try accessing a local file first if exists*/ + if (bctbx_file_exist(ZRTP_CACHE_CONFIG_FILE)==0){ + snprintf(db_file,path_max,"%s",filename); + }else{ +#ifdef _WIN32 + const char *appdata=getenv("APPDATA"); + if (appdata){ + snprintf(db_file,path_max,"%s\\%s",appdata,LINPHONE_CONFIG_DIR); + CreateDirectory(db_file,NULL); + snprintf(db_file,path_max,"%s\\%s\\%s",appdata,LINPHONE_CONFIG_DIR,filename); + } +#else + const char *home=getenv("HOME"); + if (home==NULL) home="."; + snprintf(db_file,path_max,"%s/%s",home,filename); +#endif + } + return db_file; +} int main(int argc, char *argv[]){ char *config_file; @@ -2162,7 +2191,7 @@ int main(int argc, char *argv[]){ const char *icon_name=LINPHONE_ICON_NAME; const char *app_name="Linphone"; LpConfig *factory_config; - char *chat_messages_db_file, *call_logs_db_file, *friends_db_file; + char *chat_messages_db_file, *call_logs_db_file, *friends_db_file, *zrtp_cache_db_file; GError *error=NULL; const char *tmp; const char *resources_dir; @@ -2310,7 +2339,8 @@ core_start: chat_messages_db_file=linphone_gtk_message_storage_get_db_file(NULL); call_logs_db_file = linphone_gtk_call_logs_storage_get_db_file(NULL); friends_db_file = linphone_gtk_friends_storage_get_db_file(NULL); - linphone_gtk_init_liblinphone(config_file, factory_config_file, chat_messages_db_file, call_logs_db_file, friends_db_file); + zrtp_cache_db_file = linphone_gtk_zrtp_cache_get_db_file(NULL); + linphone_gtk_init_liblinphone(config_file, factory_config_file, chat_messages_db_file, call_logs_db_file, friends_db_file, zrtp_cache_db_file); g_free(chat_messages_db_file); g_free(call_logs_db_file); g_free(friends_db_file); diff --git a/include/linphone/core.h b/include/linphone/core.h index b4aca8002..11c73821c 100644 --- a/include/linphone/core.h +++ b/include/linphone/core.h @@ -3556,16 +3556,35 @@ LINPHONE_PUBLIC void linphone_core_refresh_registers(LinphoneCore* lc); * @param[in] lc #LinphoneCore object * @param[in] file The path to the file to use to store the zrtp secrets cache. * @ingroup initializing + * @deprecated cache is now hold as sqlite db, use linphone_core_set_zrtp_cache_database_path to set path to the db and open it */ -LINPHONE_PUBLIC void linphone_core_set_zrtp_secrets_file(LinphoneCore *lc, const char* file); +LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_core_set_zrtp_secrets_file(LinphoneCore *lc, const char* file); /** * Get the path to the file storing the zrtp secrets cache. * @param[in] lc #LinphoneCore object. * @return The path to the file storing the zrtp secrets cache. * @ingroup initializing + * @deprecated cache is now hold as sqlite db, use linphone_core_get_zrtp_cache_db to get a pointer to it */ -LINPHONE_PUBLIC const char *linphone_core_get_zrtp_secrets_file(LinphoneCore *lc); +LINPHONE_PUBLIC LINPHONE_DEPRECATED const char *linphone_core_get_zrtp_secrets_file(LinphoneCore *lc); + +/** + * Get a pointer to the sqlite db holding zrtp/lime cache + * @param[in] lc #LinphoneCore object. + * @return An sqlite3 pointer cast to a void one or NULL if cache is not available(not enabled at compile or access failed) + * @ingroup initializing + */ +LINPHONE_PUBLIC void *linphone_core_get_zrtp_cache_db(LinphoneCore *lc); + +/** + * Sets the database filename where zrtp cache will be stored. + * If the file does not exist, it will be created. + * @ingroup initializing + * @param lc the linphone core + * @param path filesystem path +**/ +LINPHONE_PUBLIC void linphone_core_set_zrtp_cache_database_path(LinphoneCore *lc, const char *path); /** * Set the path to the directory storing the user's x509 certificates (used by dtls) diff --git a/mediastreamer2 b/mediastreamer2 index 1e4c039d3..a530503b9 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit 1e4c039d348a28cb9fffbcf7beb966976d1add19 +Subproject commit a530503b970d37f389e392cb5cca4c47de5e4956 diff --git a/tester/message_tester.c b/tester/message_tester.c index 45b946ebb..7540b266a 100644 --- a/tester/message_tester.c +++ b/tester/message_tester.c @@ -37,8 +37,10 @@ static char* message_external_body_url=NULL; -static const char *marie_zid_cache = "\nef7692d0792a67491ae2d44e005dbe0399643d953a2202dd9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899%s08df5907d30959b8cb70f6fff2d8febd88fb41b0c8afc39e4b972f86dd5cfe2d60f020a3fe11dc2cc0e1e8ed9341b4cd14944db806ca4fc95456bbe45d95c43a5f9aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193bcffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b7719300000078000001cf011234567889643d953a2202ee9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899%s72d80ab1cad243cf45634980c1d02cfb2df81ce0dd5dfcf1ebeacfc5345a917625d9ac653a83c4559cb0ae7394e7cd3b2d3c57bb28e62068d2df23e8f9b77193f69aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b7719322ffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b771930000000f00000000"; -static const char *pauline_zid_cache = "\n005dbe0399643d953a2202ddef7692d0792a67491ae2d44e9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899%s08df5907d30959b8cb70f6fff2d8febd88fb41b0c8afc39e4b972f86dd5cfe2d60f020a3fe11dc2cc0e1e8ed9341b4cd14944db806ca4fc95456bbe45d95c43a5f9aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193bcffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b7719300000078000001cf011234567889643d953a2202ee9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899%s81e6e6362c34dc974263d1f77cbb9a8d6d6a718330994379099a8fa19fb12faa25d9ac653a83c4559cb0ae7394e7cd3b2d3c57bb28e62068d2df23e8f9b77193f69aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b7719322ffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b771930000002e0000000001"; +/* sql cache creation string, contains 3 string to be inserted : selfuri/selfuri/peeruri */ +static const char *marie_zid_sqlcache = "BEGIN TRANSACTION; CREATE TABLE IF NOT EXISTS ziduri (zuid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,zid BLOB NOT NULL DEFAULT '000000000000',selfuri TEXT NOT NULL DEFAULT 'unset',peeruri TEXT NOT NULL DEFAULT 'unset'); INSERT INTO `ziduri` (zuid,zid,selfuri,peeruri) VALUES (1,X'4ddc8042bee500ad0366bf93','%s','self'), (2,X'bcb4028bf55e1b7ac4c4edee','%s','%s'); CREATE TABLE IF NOT EXISTS zrtp (zuid INTEGER NOT NULL DEFAULT 0 UNIQUE,rs1 BLOB DEFAULT NULL,rs2 BLOB DEFAULT NULL,aux BLOB DEFAULT NULL,pbx BLOB DEFAULT NULL,pvs BLOB DEFAULT NULL,FOREIGN KEY(zuid) REFERENCES ziduri(zuid) ON UPDATE CASCADE ON DELETE CASCADE); INSERT INTO `zrtp` (zuid,rs1,rs2,aux,pbx,pvs) VALUES (2,X'f0e0ad4d3d4217ba4048d1553e5ab26fae0b386cdac603f29a66d5f4258e14ef',NULL,NULL,NULL,X'01'); CREATE TABLE IF NOT EXISTS lime (zuid INTEGER NOT NULL DEFAULT 0 UNIQUE,sndKey BLOB DEFAULT NULL,rcvKey BLOB DEFAULT NULL,sndSId BLOB DEFAULT NULL,rcvSId BLOB DEFAULT NULL,sndIndex BLOB DEFAULT NULL,rcvIndex BLOB DEFAULT NULL,valid BLOB DEFAULT NULL,FOREIGN KEY(zuid) REFERENCES ziduri(zuid) ON UPDATE CASCADE ON DELETE CASCADE); INSERT INTO `lime` (zuid,sndKey,rcvKey,sndSId,rcvSId,sndIndex,rcvIndex,valid) VALUES (2,X'97c75a5a92a041b415296beec268efc3373ef4aa8b3d5f301ac7522a7fb4e332',x'3b74b709b961e5ebccb1db6b850ea8c1f490546d6adee2f66b5def7093cead3d',X'e2ebca22ad33071bc37631393bf25fc0a9badeea7bf6dcbcb5d480be7ff8c5ea',X'a2086d195344ec2997bf3de7441d261041cda5d90ed0a0411ab2032e5860ea48',X'33376935',X'7ce32d86',X'0000000000000000'); COMMIT;"; + +static const char *pauline_zid_sqlcache = "BEGIN TRANSACTION; CREATE TABLE IF NOT EXISTS ziduri (zuid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,zid BLOB NOT NULL DEFAULT '000000000000',selfuri TEXT NOT NULL DEFAULT 'unset',peeruri TEXT NOT NULL DEFAULT 'unset'); INSERT INTO `ziduri` (zuid,zid,selfuri,peeruri) VALUES (1,X'bcb4028bf55e1b7ac4c4edee','%s','self'), (2,X'4ddc8042bee500ad0366bf93','%s','%s'); CREATE TABLE IF NOT EXISTS zrtp (zuid INTEGER NOT NULL DEFAULT 0 UNIQUE,rs1 BLOB DEFAULT NULL,rs2 BLOB DEFAULT NULL,aux BLOB DEFAULT NULL,pbx BLOB DEFAULT NULL,pvs BLOB DEFAULT NULL,FOREIGN KEY(zuid) REFERENCES ziduri(zuid) ON UPDATE CASCADE ON DELETE CASCADE); INSERT INTO `zrtp` (zuid,rs1,rs2,aux,pbx,pvs) VALUES (2,X'f0e0ad4d3d4217ba4048d1553e5ab26fae0b386cdac603f29a66d5f4258e14ef',NULL,NULL,NULL,X'01'); CREATE TABLE IF NOT EXISTS lime (zuid INTEGER NOT NULL DEFAULT 0 UNIQUE,sndKey BLOB DEFAULT NULL,rcvKey BLOB DEFAULT NULL,sndSId BLOB DEFAULT NULL,rcvSId BLOB DEFAULT NULL,sndIndex BLOB DEFAULT NULL,rcvIndex BLOB DEFAULT NULL,valid BLOB DEFAULT NULL,FOREIGN KEY(zuid) REFERENCES ziduri(zuid) ON UPDATE CASCADE ON DELETE CASCADE); INSERT INTO `lime` (zuid,rcvKey,sndKey,rcvSId,sndSId,rcvIndex,sndIndex,valid) VALUES (2,X'97c75a5a92a041b415296beec268efc3373ef4aa8b3d5f301ac7522a7fb4e332',x'3b74b709b961e5ebccb1db6b850ea8c1f490546d6adee2f66b5def7093cead3d',X'e2ebca22ad33071bc37631393bf25fc0a9badeea7bf6dcbcb5d480be7ff8c5ea',X'a2086d195344ec2997bf3de7441d261041cda5d90ed0a0411ab2032e5860ea48',X'33376935',X'7ce32d86',X'0000000000000000'); COMMIT;"; void text_message_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddress *from_address, const char *msg) { stats* counters = get_stats(lc); @@ -864,42 +866,59 @@ static void info_message_with_body(void){ info_message_base(TRUE); } -static FILE* fopen_from_write_dir(const char * name, const char * mode) { - char *filepath = bc_tester_file(name); - FILE * file = fopen(filepath,mode); - bc_free(filepath); - return file; -} - static int enable_lime_for_message_test(LinphoneCoreManager *marie, LinphoneCoreManager *pauline) { +#ifdef SQLITE_STORAGE_ENABLED char* filepath = NULL; - FILE *ZIDCacheMarieFD = NULL, *ZIDCachePaulineFD = NULL; + char* stmt = NULL; + char* errmsg=NULL; + int ret = 0; + char* paulineUri = NULL; + char* marieUri = NULL; - if (!linphone_core_lime_available(marie->lc)) { + if (!linphone_core_lime_available(marie->lc) || !linphone_core_lime_available(pauline->lc)) { ms_warning("Lime not available, skiping"); return -1; } /* make sure lime is enabled */ linphone_core_enable_lime(marie->lc, LinphoneLimeMandatory); linphone_core_enable_lime(pauline->lc, LinphoneLimeMandatory); - - /* set the zid caches files : create two ZID cache from this valid one inserting the auto-generated sip URI for the peer account as keys in ZID cache are indexed by peer sip uri */ - ZIDCacheMarieFD = fopen_from_write_dir("tmpZIDCacheMarie.xml", "w"); - ZIDCachePaulineFD = fopen_from_write_dir("tmpZIDCachePauline.xml", "w"); - fprintf(ZIDCacheMarieFD, marie_zid_cache, linphone_address_as_string_uri_only(pauline->identity), linphone_address_as_string_uri_only(pauline->identity)); - fprintf(ZIDCachePaulineFD, pauline_zid_cache, linphone_address_as_string_uri_only(marie->identity), linphone_address_as_string_uri_only(marie->identity)); - fclose(ZIDCacheMarieFD); - fclose(ZIDCachePaulineFD); - filepath = bc_tester_file("tmpZIDCacheMarie.xml"); - linphone_core_set_zrtp_secrets_file(marie->lc, filepath); + /* create temporary cache files: setting the database_path will create and initialise the files */ + remove(bc_tester_file("tmpZIDCacheMarie.sqlite")); + remove(bc_tester_file("tmpZIDCachePauline.sqlite")); + filepath = bc_tester_file("tmpZIDCacheMarie.sqlite"); + linphone_core_set_zrtp_cache_database_path(marie->lc, filepath); + bc_free(filepath); + filepath = bc_tester_file("tmpZIDCachePauline.sqlite"); + linphone_core_set_zrtp_cache_database_path(pauline->lc, filepath); bc_free(filepath); - filepath = bc_tester_file("tmpZIDCachePauline.xml"); - linphone_core_set_zrtp_secrets_file(pauline->lc, filepath); - bc_free(filepath); + /* caches are empty, populate them */ + paulineUri = linphone_address_as_string_uri_only(pauline->identity); + marieUri = linphone_address_as_string_uri_only(marie->identity); + + stmt = sqlite3_mprintf(marie_zid_sqlcache, marieUri, marieUri, paulineUri); + ret = sqlite3_exec(linphone_core_get_zrtp_cache_db(marie->lc),stmt,NULL,NULL,&errmsg); + sqlite3_free(stmt); + if (ret != SQLITE_OK) { + ms_warning("Lime can't populate marie's sqlite cache: %s", errmsg); + sqlite3_free(errmsg); + return -1; + } + stmt = sqlite3_mprintf(pauline_zid_sqlcache, paulineUri, paulineUri, marieUri); + ret = sqlite3_exec(linphone_core_get_zrtp_cache_db(pauline->lc),stmt,NULL,NULL,&errmsg); + sqlite3_free(stmt); + if (ret != SQLITE_OK) { + ms_warning("Lime can't populate pauline's sqlite cache: %s", errmsg); + sqlite3_free(errmsg); + return -1; + } + return 0; +#else /* SQLITE_STORAGE_ENABLED */ + return -1; /* cannot enable lime without SQLITE_STORAGE */ +#endif /* SQLITE_STORAGE_ENABLED */ } static void _is_composing_notification(bool_t lime_enabled) { @@ -924,17 +943,19 @@ static void _is_composing_notification(bool_t lime_enabled) { end: linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); - remove("tmpZIDCacheMarie.xml"); - remove("tmpZIDCachePauline.xml"); + remove("tmpZIDCacheMarie.sqlite"); + remove("tmpZIDCachePauline.sqlite"); } static void is_composing_notification(void) { _is_composing_notification(FALSE); } +#ifdef SQLITE_STORAGE_ENABLED static void is_composing_notification_with_lime(void) { _is_composing_notification(TRUE); } +#endif static void _imdn_notifications(bool_t with_lime) { LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); @@ -975,8 +996,8 @@ static void _imdn_notifications(bool_t with_lime) { end: linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); - remove("tmpZIDCacheMarie.xml"); - remove("tmpZIDCachePauline.xml"); + remove("tmpZIDCacheMarie.sqlite"); + remove("tmpZIDCachePauline.sqlite"); } static void _im_notification_policy(bool_t with_lime) { @@ -1067,8 +1088,8 @@ static void _im_notification_policy(bool_t with_lime) { end: linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); - remove("tmpZIDCacheMarie.xml"); - remove("tmpZIDCachePauline.xml"); + remove("tmpZIDCacheMarie.sqlite"); + remove("tmpZIDCachePauline.sqlite"); } static void imdn_notifications(void) { @@ -1079,6 +1100,7 @@ static void im_notification_policy(void) { _im_notification_policy(FALSE); } +#ifdef SQLITE_STORAGE_ENABLED static void imdn_notifications_with_lime(void) { _imdn_notifications(TRUE); } @@ -1086,17 +1108,16 @@ static void imdn_notifications_with_lime(void) { static void im_notification_policy_with_lime(void) { _im_notification_policy(TRUE); } +#endif static void _im_error_delivery_notification(bool_t online) { - FILE *ZIDCacheMarieFD, *ZIDCachePaulineFD; LinphoneChatRoom *chat_room; - char *marie_filepath; - char *pauline_filepath; LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager *pauline = linphone_core_manager_new( "pauline_tcp_rc"); LinphoneChatMessage *msg; LinphoneChatMessageCbs *cbs; int dummy = 0; + void *zrtp_cache_db_holder=NULL; if (!linphone_core_lime_available(marie->lc)) { ms_warning("Lime not available, skiping"); @@ -1104,23 +1125,7 @@ static void _im_error_delivery_notification(bool_t online) { } /* Make sure lime is enabled */ - linphone_core_enable_lime(marie->lc, LinphoneLimeMandatory); - linphone_core_enable_lime(pauline->lc, LinphoneLimeMandatory); - - /* Set the zid cache files : create two ZID cache from this valid one inserting the auto-generated sip URI for the peer account as keys in ZID cache are indexed by peer sip uri. */ - ZIDCacheMarieFD = fopen_from_write_dir("tmpZIDCacheMarie.xml", "w"); - ZIDCachePaulineFD = fopen_from_write_dir("tmpZIDCachePauline.xml", "w"); - fprintf(ZIDCacheMarieFD, marie_zid_cache, linphone_address_as_string_uri_only(pauline->identity), linphone_address_as_string_uri_only(pauline->identity)); - fprintf(ZIDCachePaulineFD, pauline_zid_cache, linphone_address_as_string_uri_only(marie->identity), linphone_address_as_string_uri_only(marie->identity)); - fclose(ZIDCacheMarieFD); - fclose(ZIDCachePaulineFD); - - marie_filepath = bc_tester_file("tmpZIDCacheMarie.xml"); - linphone_core_set_zrtp_secrets_file(marie->lc, marie_filepath); - - pauline_filepath = bc_tester_file("tmpZIDCachePauline.xml"); - linphone_core_set_zrtp_secrets_file(pauline->lc, pauline_filepath); - bc_free(pauline_filepath); + if (enable_lime_for_message_test(marie, pauline) < 0) goto end; chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity); @@ -1134,8 +1139,9 @@ static void _im_error_delivery_notification(bool_t online) { BC_ASSERT_PTR_NOT_NULL(linphone_core_get_chat_room(marie->lc, pauline->identity)); - /* Clear the ZID cache of the receiver of the chat message and enable all IM notifications */ - linphone_core_set_zrtp_secrets_file(marie->lc, NULL); + /* Temporary disabling receiver cache and enable all IM notifications */ + zrtp_cache_db_holder = marie->lc->zrtp_cache_db; + marie->lc->zrtp_cache_db = NULL; linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(marie->lc)); linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(pauline->lc)); @@ -1156,19 +1162,18 @@ static void _im_error_delivery_notification(bool_t online) { BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageNotDelivered, 1)); /* Restore the ZID cache of the receiver and resend the chat message */ - linphone_core_set_zrtp_secrets_file(marie->lc, marie_filepath); + marie->lc->zrtp_cache_db = zrtp_cache_db_holder; linphone_chat_message_ref(msg); linphone_chat_message_resend(msg); BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 2)); /* Check the new message is now received */ BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageDeliveredToUser, 1)); linphone_chat_message_unref(msg); - bc_free(marie_filepath); end: linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); - remove("tmpZIDCacheMarie.xml"); - remove("tmpZIDCachePauline.xml"); + remove("tmpZIDCacheMarie.sqlite"); + remove("tmpZIDCachePauline.sqlite"); } static void im_error_delivery_notification_online(void) { @@ -1179,10 +1184,9 @@ static void im_error_delivery_notification_offline(void) { _im_error_delivery_notification(FALSE); } +#ifdef SQLITE_STORAGE_ENABLED static void lime_text_message(void) { - FILE *ZIDCacheMarieFD, *ZIDCachePaulineFD; LinphoneChatRoom* chat_room; - char* filepath; LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc"); @@ -1190,25 +1194,8 @@ static void lime_text_message(void) { ms_warning("Lime not available, skiping"); goto end; } - /* make sure lime is enabled */ - linphone_core_enable_lime(marie->lc, LinphoneLimeMandatory); - linphone_core_enable_lime(pauline->lc, LinphoneLimeMandatory); - /* set the zid caches files : create two ZID cache from this valid one inserting the auto-generated sip URI for the peer account as keys in ZID cache are indexed by peer sip uri */ - ZIDCacheMarieFD = fopen_from_write_dir("tmpZIDCacheMarie.xml", "w"); - ZIDCachePaulineFD = fopen_from_write_dir("tmpZIDCachePauline.xml", "w"); - fprintf(ZIDCacheMarieFD, marie_zid_cache, linphone_address_as_string_uri_only(pauline->identity), linphone_address_as_string_uri_only(pauline->identity)); - fprintf(ZIDCachePaulineFD, pauline_zid_cache, linphone_address_as_string_uri_only(marie->identity), linphone_address_as_string_uri_only(marie->identity)); - fclose(ZIDCacheMarieFD); - fclose(ZIDCachePaulineFD); - - filepath = bc_tester_file("tmpZIDCacheMarie.xml"); - linphone_core_set_zrtp_secrets_file(marie->lc, filepath); - bc_free(filepath); - - filepath = bc_tester_file("tmpZIDCachePauline.xml"); - linphone_core_set_zrtp_secrets_file(pauline->lc, filepath); - bc_free(filepath); + if (enable_lime_for_message_test(marie, pauline) < 0) goto end; chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity); @@ -1222,16 +1209,14 @@ static void lime_text_message(void) { BC_ASSERT_PTR_NOT_NULL(linphone_core_get_chat_room(marie->lc,pauline->identity)); end: - remove("tmpZIDCacheMarie.xml"); - remove("tmpZIDCachePauline.xml"); + remove("tmpZIDCacheMarie.sqlite"); + remove("tmpZIDCachePauline.sqlite"); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } static void lime_text_message_to_non_lime(bool_t sender_policy_mandatory, bool_t lime_key_available) { - FILE *ZIDCachePaulineFD; LinphoneChatRoom* chat_room; - char* filepath; LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc"); @@ -1244,14 +1229,11 @@ static void lime_text_message_to_non_lime(bool_t sender_policy_mandatory, bool_t linphone_core_enable_lime(pauline->lc, sender_policy_mandatory ? LinphoneLimeMandatory : LinphoneLimePreferred); if (lime_key_available) { - /* set the zid caches files : create two ZID cache from this valid one inserting the auto-generated sip URI for the peer account as keys in ZID cache are indexed by peer sip uri */ - ZIDCachePaulineFD = fopen_from_write_dir("tmpZIDCachePauline.xml", "w"); - fprintf(ZIDCachePaulineFD, pauline_zid_cache, linphone_address_as_string_uri_only(marie->identity), linphone_address_as_string_uri_only(marie->identity)); - fclose(ZIDCachePaulineFD); - - filepath = bc_tester_file("tmpZIDCachePauline.xml"); - linphone_core_set_zrtp_secrets_file(pauline->lc, filepath); - bc_free(filepath); + /* enable lime for both parts */ + if (enable_lime_for_message_test(marie, pauline) < 0) goto end; + /* but then disable marie */ + sqlite3_close(marie->lc->zrtp_cache_db); + marie->lc->zrtp_cache_db = NULL; } chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity); @@ -1282,7 +1264,7 @@ static void lime_text_message_to_non_lime(bool_t sender_policy_mandatory, bool_t BC_ASSERT_PTR_NOT_NULL(linphone_core_get_chat_room(marie->lc,pauline->identity)); end: - remove("tmpZIDCachePauline.xml"); + remove("tmpZIDCachePauline.sqlite"); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } @@ -1304,12 +1286,9 @@ static void lime_text_message_without_cache(void) { } void lime_transfer_message_base(bool_t encrypt_file,bool_t download_file_from_stored_msg, bool_t use_file_body_handler_in_upload, bool_t use_file_body_handler_in_download) { - FILE *ZIDCacheMarieFD, *ZIDCachePaulineFD; LinphoneCoreManager *marie, *pauline; LinphoneChatMessage *msg; LinphoneChatMessageCbs *cbs; - char *pauline_id, *marie_id; - char *filepath; char *send_filepath = bc_tester_res("sounds/sintel_trailer_opus_h264.mkv"); char *receive_filepath = bc_tester_file("receive_file.dump"); MSList * msg_list = NULL; @@ -1325,33 +1304,12 @@ void lime_transfer_message_base(bool_t encrypt_file,bool_t download_file_from_st goto end; } /* make sure lime is enabled */ - linphone_core_enable_lime(marie->lc, LinphoneLimeMandatory); - linphone_core_enable_lime(pauline->lc, LinphoneLimeMandatory); + enable_lime_for_message_test(marie, pauline); + if (!encrypt_file) { LpConfig *pauline_lp = linphone_core_get_config(pauline->lc); lp_config_set_int(pauline_lp, "sip", "lime_for_file_sharing", 0); } - - /* set the zid caches files : create two ZID cache from this valid one inserting the auto-generated sip URI for the peer account as keys in ZID cache are indexed by peer sip uri */ - ZIDCacheMarieFD = fopen_from_write_dir("tmpZIDCacheMarie.xml", "wb"); - ZIDCachePaulineFD = fopen_from_write_dir("tmpZIDCachePauline.xml", "wb"); - pauline_id = linphone_address_as_string_uri_only(pauline->identity); - marie_id = linphone_address_as_string_uri_only(marie->identity); - fprintf(ZIDCacheMarieFD, "\nef7692d0792a67491ae2d44e005dbe0399643d953a2202dd9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899%s08df5907d30959b8cb70f6fff2d8febd88fb41b0c8afc39e4b972f86dd5cfe2d60f020a3fe11dc2cc0e1e8ed9341b4cd14944db806ca4fc95456bbe45d95c43a5f9aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193bcffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b7719300000078000001cf011234567889643d953a2202ee9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778csal_set_uuid(lc->sal, account->instance_id);bdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899%s72d80ab1cad243cf45634980c1d02cfb2df81ce0dd5dfcf1ebeacfc5345a917625d9ac653a83c4559cb0ae7394e7cd3b2d3c57bb28e62068d2df23e8f9b77193f69aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b7719322ffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b771930000000f00000000", pauline_id, pauline_id); - fprintf(ZIDCachePaulineFD, pauline_zid_cache, marie_id, marie_id); - fclose(ZIDCacheMarieFD); - fclose(ZIDCachePaulineFD); - ms_free(marie_id); - ms_free(pauline_id); - - filepath = bc_tester_file("tmpZIDCacheMarie.xml"); - linphone_core_set_zrtp_secrets_file(marie->lc, filepath); - bc_free(filepath); - - filepath = bc_tester_file("tmpZIDCachePauline.xml"); - linphone_core_set_zrtp_secrets_file(pauline->lc, filepath); - bc_free(filepath); - /* Globally configure an http file transfer server. */ linphone_core_set_file_transfer_server(pauline->lc,"https://www.linphone.org:444/lft.php"); @@ -1402,8 +1360,8 @@ void lime_transfer_message_base(bool_t encrypt_file,bool_t download_file_from_st BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageDelivered,1, int, "%d"); BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneFileTransferDownloadSuccessful,1, int, "%d"); end: - remove("tmpZIDCacheMarie.xml"); - remove("tmpZIDCachePauline.xml"); + remove("tmpZIDCacheMarie.sqlite"); + remove("tmpZIDCachePauline.sqlite"); remove(receive_filepath); bc_free(send_filepath); bc_free(receive_filepath); @@ -1439,230 +1397,19 @@ static void lime_transfer_message_without_encryption_2(void) { lime_transfer_message_base(FALSE, FALSE, TRUE, FALSE); } -static void printHex(char *title, uint8_t *data, size_t length) { - size_t i; - char debug_string_buffer[2048]; - char *debug_string = debug_string_buffer; - sprintf (debug_string, "%s : ", title); - debug_string += strlen(title)+3; - for (i=0; i\r\nef7692d0792a67491ae2d44e005dbe0399643d953a2202dd9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899pipo1@pipo.com963c57bb28e62068d2df23e8f9b771932d3c57bb28e62068d2df23e8f9b7719306d9ac653a83c4559cb0ae7394e7cd3b2d3c57bb28e62068d2df23e8f9b771935f9aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b7719303ffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b7719300000069000001e9011234567889643d953a2202ee9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899pipo1@pipo.com123456789012345678901234567890123456765431262068d2df23e8f9b7719325d9ac653a83c4559cb0ae7394e7cd3b2d3c57bb28e62068d2df23e8f9b77193f69aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b7719322ffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b77193000000010000000001\r\n"; - char cachedStringBufferExpected[2048]; - char cachedStringBufferActual[2048]; - char cachedStringBuffer[2048]; - int retval; - size_t size; - uint8_t *cacheBufferString; - xmlDocPtr cacheBufferAlice; - xmlDocPtr cacheBufferBob; - uint8_t *multipartMessage = NULL; - uint8_t *decryptedMessage = NULL; - char *decryptedContentType = NULL; - xmlChar *xmlStringOutput; - int xmlStringLength; - limeURIKeys_t associatedKeys; - int i; - limeKey_t associatedKey; - uint8_t targetZID[12] = {0x00, 0x5d, 0xbe, 0x03, 0x99, 0x64, 0x3d, 0x95, 0x3a, 0x22, 0x02, 0xdd}; - uint8_t senderZID[12] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x70, 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0}; - uint8_t encryptedMessage[1024]; - uint8_t plainMessage[1024]; - uint8_t receiverZID[12]; - xmlDocPtr cacheBuffer; - FILE *CACHE; + LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc"); - /**** Low level tests using on cache file to extract keys, encrypt/decrypt ****/ - /**** use functions that are not directly used by external entities ****/ + BC_ASSERT_EQUAL(enable_lime_for_message_test(marie, pauline), 0, int, "%d"); - /* create and load cache file */ - CACHE = fopen_from_write_dir("ZIDCache.xml", "wb"); - fprintf (CACHE, "\r\nef7692d0792a67491ae2d44e005dbe0399643d953a2202dd9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899pipo1@pipo.com963c57bb28e62068d2df23e8f9b771932d3c57bb28e62068d2df23e8f9b7719305d9ac653a83c4559cb0ae7394e7cd3b2d3c57bb28e62068d2df23e8f9b771935f9aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b7719302ffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b7719300000069000001e8011234567889643d953a2202ee9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899pipo1@pipo.com123456789012345678901234567890123456765431262068d2df23e8f9b7719325d9ac653a83c4559cb0ae7394e7cd3b2d3c57bb28e62068d2df23e8f9b77193f69aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b7719322ffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b77193000000010000000001"); - fclose(CACHE); - CACHE = fopen_from_write_dir("ZIDCache.xml", "rb+"); - cacheBufferString = (uint8_t*) ms_load_file_content(CACHE, &size); - *(cacheBufferString+size) = '\0'; - fclose(CACHE); - /* parse it to an xmlDoc */ - cacheBuffer = xmlParseDoc(cacheBufferString); - ms_free(cacheBufferString); - - /* get data from cache : sender */ - associatedKeys.peerURI = (uint8_t *)malloc(15); - memcpy(associatedKeys.peerURI, "pipo1@pipo.com", 15); - associatedKeys.associatedZIDNumber = 0; - retval = lime_getCachedSndKeysByURI(cacheBuffer, &associatedKeys); - BC_ASSERT_EQUAL(retval, 0, int, "%d"); - BC_ASSERT_EQUAL(associatedKeys.associatedZIDNumber, 2, int, "%d"); /* there are 2 keys associated to pipo1@pipo.com address in the cache above*/ - ms_message("Get cached key by URI, for sender, return %d keys", associatedKeys.associatedZIDNumber); - - for (i=0; ipeerZID, 12); - printHex("key", associatedKeys.peerKeys[i]->key, 32); - printHex("sessionID", associatedKeys.peerKeys[i]->sessionId, 32); - ms_message("session index %d\n", associatedKeys.peerKeys[i]->sessionIndex); - } - - /* get data from cache : receiver */ - memcpy(associatedKey.peerZID, targetZID, 12); - retval = lime_getCachedRcvKeyByZid(cacheBuffer, &associatedKey); - BC_ASSERT_EQUAL(retval, 0, int, "%d"); - printHex("Got receiver key for ZID", targetZID, 12); - printHex("Key", associatedKey.key, 32); - printHex("sessionID", associatedKey.sessionId, 32); - ms_message("session index %d\n", associatedKey.sessionIndex); - - /* encrypt/decrypt a msg */ - lime_encryptMessage(associatedKeys.peerKeys[0], (uint8_t *)PLAIN_TEXT_TEST_MESSAGE, (uint32_t)strlen(PLAIN_TEXT_TEST_MESSAGE), senderZID, encryptedMessage); - printHex("Ciphered", encryptedMessage, strlen((char *)encryptedMessage)); - /* invert sender and receiverZID to decrypt/authenticate */ - memcpy(receiverZID, associatedKeys.peerKeys[0]->peerZID, 12); - memcpy(associatedKeys.peerKeys[0]->peerZID, senderZID, 12); - retval = lime_decryptMessage(associatedKeys.peerKeys[0], encryptedMessage, (uint32_t)strlen(PLAIN_TEXT_TEST_MESSAGE)+16, receiverZID, plainMessage); - BC_ASSERT_EQUAL(retval, 0, int, "%d"); - BC_ASSERT_STRING_EQUAL((char *)plainMessage, (char *)PLAIN_TEXT_TEST_MESSAGE); - ms_message("Decrypt and auth returned %d\nPlain text is %s\n", retval, plainMessage); - - /* update receiver data */ - associatedKey.sessionIndex++; - associatedKey.key[0]++; - associatedKey.sessionId[0]++; - retval = lime_setCachedKey(cacheBuffer, &associatedKey, LIME_RECEIVER, 0); - BC_ASSERT_EQUAL(retval, 0, int, "%d"); - - /* update sender data */ - associatedKeys.peerKeys[0]->sessionIndex++; - associatedKeys.peerKeys[0]->key[0]++; - associatedKeys.peerKeys[0]->sessionId[0]++; - retval = lime_setCachedKey(cacheBuffer, associatedKeys.peerKeys[0], LIME_SENDER, 0); - BC_ASSERT_EQUAL(retval, 0, int, "%d"); - - /* free memory */ - lime_freeKeys(&associatedKeys); - - /* write the file */ - - /* dump the xml document into a string */ - xmlDocDumpFormatMemoryEnc(cacheBuffer, &xmlStringOutput, &xmlStringLength, "UTF-8", 0); - /* must strip buffers of their \n\r or strcmp won't like it */ - stripnCR(cachedStringBufferExpected, pattern_ZIDCache_noValidity, strlen(pattern_ZIDCache_noValidity)); - stripnCR(cachedStringBufferActual, (const char *)xmlStringOutput, strlen((const char *)xmlStringOutput)); - BC_ASSERT_NSTRING_EQUAL(cachedStringBufferExpected, cachedStringBufferActual, strlen(cachedStringBufferExpected)); - - /* write it to the file */ - CACHE = fopen_from_write_dir("ZIDCache.xml", "w+"); - fwrite(xmlStringOutput, 1, xmlStringLength, CACHE); - xmlFree(xmlStringOutput); - fclose(CACHE); - xmlFreeDoc(cacheBuffer); - - - /**** Higher level tests using 2 caches to encrypt/decrypt a msg ****/ - /* Create Alice cache file and then load it */ - CACHE = fopen_from_write_dir("ZIDCacheAlice.xml", "wb"); - fprintf(CACHE, "\r\nef7692d0792a67491ae2d44e005dbe0399643d953a2202dd9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899sip:pauline@sip.example.org9111ebeb52e50edcc6fcb3eea1a2d3ae3c2c75d3668923e83c59d0f47245515060f020a3fe11dc2cc0e1e8ed9341b4cd14944db806ca4fc95456bbe45d95c43a5f9aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193bcffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b7719300000080000001cf0100000000386d43801234567889643d953a2202ee9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899sip:pauline@sip.example.org72d80ab1cad243cf45634980c1d02cfb2df81ce0dd5dfcf1ebeacfc5345a917625d9ac653a83c4559cb0ae7394e7cd3b2d3c57bb28e62068d2df23e8f9b77193f69aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b7719322ffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b771930000000f0000000000000000386d4380"); - fclose(CACHE); - CACHE = fopen_from_write_dir("ZIDCacheAlice.xml", "rb+"); - cacheBufferString = (uint8_t *)ms_load_file_content(CACHE, &size); - *(cacheBufferString+size) = '\0'; - fclose(CACHE); - /* parse it to an xmlDoc */ - cacheBufferAlice = xmlParseDoc(cacheBufferString); - ms_free(cacheBufferString); - - /* Create Bob cache file and then load it */ - CACHE = fopen_from_write_dir("ZIDCacheBob.xml", "wb"); - fprintf(CACHE, "\n005dbe0399643d953a2202ddef7692d0792a67491ae2d44e9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899sip:marie@sip.example.org9111ebeb52e50edcc6fcb3eea1a2d3ae3c2c75d3668923e83c59d0f47245515060f020a3fe11dc2cc0e1e8ed9341b4cd14944db806ca4fc95456bbe45d95c43a5f9aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193bcffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b7719300000080000001cf011234567889643d953a2202ee9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899sip:marie@sip.example.org81e6e6362c34dc974263d1f77cbb9a8d6d6a718330994379099a8fa19fb12faa25d9ac653a83c4559cb0ae7394e7cd3b2d3c57bb28e62068d2df23e8f9b77193f69aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b7719322ffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b771930000002e0000000001"); - fclose(CACHE); - CACHE = fopen_from_write_dir("ZIDCacheBob.xml", "rb+"); - cacheBufferString = (uint8_t *)ms_load_file_content(CACHE, &size); - *(cacheBufferString+size) = '\0'; - fclose(CACHE); - /* parse it to an xmlDoc */ - cacheBufferBob = xmlParseDoc(cacheBufferString); - ms_free(cacheBufferString); - - - /*Try to encrypt the message, but it shall fail due to expired key */ - - /* encrypt a msg */ - retval = lime_createMultipartMessage(cacheBufferAlice, "text/plain", (uint8_t *)PLAIN_TEXT_TEST_MESSAGE, (uint8_t *)"sip:pauline@sip.example.org", &multipartMessage); - BC_ASSERT_EQUAL(retval, LIME_PEER_KEY_HAS_EXPIRED, int, "%d"); - - /* reload a cache but with valid key (time bomb: validity is set to the 2038 bug epoch even if we are not prone to it) */ - sprintf(cachedStringBuffer, "\r\nef7692d0792a67491ae2d44e005dbe0399643d953a2202dd9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899sip:pauline@sip.example.org9111ebeb52e50edcc6fcb3eea1a2d3ae3c2c75d3668923e83c59d0f47245515060f020a3fe11dc2cc0e1e8ed9341b4cd14944db806ca4fc95456bbe45d95c43a5f9aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b77193bcffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b7719300000080000001cf01000000007fffffff1234567889643d953a2202ee9b5c8f06f3b6c2c695f2dfc3c26f31f5fef8661f8c5fe7c95aeb5c5b0435b045f8324dd18ea905171ec2be89f879d01d5994132048d92ea020778cbdf31c605e2fdcef69380937c2cf221f7d11526f286c39f49641452ba9012521c705094899sip:pauline@sip.example.org72d80ab1cad243cf45634980c1d02cfb2df81ce0dd5dfcf1ebeacfc5345a917625d9ac653a83c4559cb0ae7394e7cd3b2d3c57bb28e62068d2df23e8f9b77193f69aa1e5e4c7ec88fa389a9f6b8879b42d3c57bb28e62068d2df23e8f9b7719322ffd51e7316a6c6f53a50fcf01b01bf2d3c57bb28e62068d2df23e8f9b771930000000f00000000000000007fffffff"); - xmlFreeDoc(cacheBufferAlice); - cacheBufferAlice = xmlParseDoc((unsigned char *)cachedStringBuffer); - - /* retry to encrypt a msg */ - retval = lime_createMultipartMessage(cacheBufferAlice, "text/plain", (uint8_t *)PLAIN_TEXT_TEST_MESSAGE, (uint8_t *)"sip:pauline@sip.example.org", &multipartMessage); - BC_ASSERT_EQUAL(retval, 0, int, "%d"); - if (retval == 0) { - ms_message("Encrypted msg created is %s", multipartMessage); - } - - /* decrypt the multipart msg */ - retval = lime_decryptMultipartMessage(cacheBufferBob, multipartMessage, &decryptedMessage, &decryptedContentType, 1000); - - BC_ASSERT_EQUAL(retval, 0, int, "%d"); - if (retval == 0) { - BC_ASSERT_STRING_EQUAL((char *)decryptedMessage, (char *)PLAIN_TEXT_TEST_MESSAGE); - BC_ASSERT_STRING_EQUAL((char *)decryptedContentType, "text/plain"); - ms_message("Succesfully decrypted msg is %s", decryptedMessage); - } - ms_free(multipartMessage); - ms_free(decryptedMessage); - ms_free(decryptedContentType); - - /* update ZID files */ - /* dump the xml document into a string */ - xmlDocDumpFormatMemoryEnc(cacheBufferAlice, &xmlStringOutput, &xmlStringLength, "UTF-8", 0); - /* write it to the file */ - CACHE = fopen_from_write_dir("ZIDCacheAlice.xml", "wb+"); - fwrite(xmlStringOutput, 1, xmlStringLength, CACHE); - xmlFree(xmlStringOutput); - fclose(CACHE); - - xmlDocDumpFormatMemoryEnc(cacheBufferBob, &xmlStringOutput, &xmlStringLength, "UTF-8", 0); - /* write it to the file */ - CACHE = fopen_from_write_dir("ZIDCacheBob.xml", "wb+"); - fwrite(xmlStringOutput, 1, xmlStringLength, CACHE); - xmlFree(xmlStringOutput); - fclose(CACHE); - - - xmlFreeDoc(cacheBufferAlice); - xmlFreeDoc(cacheBufferBob); - remove("ZIDCache.xml"); - remove("ZIDCacheAlice.xml"); - remove("ZIDCacheBob.xml"); - } else { - ms_warning("Lime not available, skiping"); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + /* TODO: perform more elaborate testing */ } } -#ifdef SQLITE_STORAGE_ENABLED - /* * Copy file "from" to file "to". * Destination file is truncated if existing. @@ -1925,7 +1672,7 @@ void crash_during_file_transfer(void) { linphone_core_manager_destroy(marie); } -#endif +#endif /* SQLITE_STORAGE_ENABLED */ static void text_status_after_destroying_chat_room(void) { LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); @@ -2492,8 +2239,8 @@ void _text_message_with_custom_content_type(bool_t with_lime) { end: linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); - remove("tmpZIDCacheMarie.xml"); - remove("tmpZIDCachePauline.xml"); + remove("tmpZIDCacheMarie.sqlite"); + remove("tmpZIDCachePauline.sqlite"); } void text_message_with_custom_content_type(void) { @@ -2600,9 +2347,10 @@ test_t message_tests[] = { TEST_NO_TAG("Info message", info_message), TEST_NO_TAG("Info message with body", info_message_with_body), TEST_NO_TAG("IsComposing notification", is_composing_notification), - TEST_ONE_TAG("IsComposing notification lime", is_composing_notification_with_lime, "LIME"), TEST_NO_TAG("IMDN notifications", imdn_notifications), TEST_NO_TAG("IM notification policy", im_notification_policy), +#ifdef SQLITE_STORAGE_ENABLED + TEST_ONE_TAG("IsComposing notification lime", is_composing_notification_with_lime, "LIME"), TEST_ONE_TAG("IMDN notifications with lime", imdn_notifications_with_lime, "LIME"), TEST_ONE_TAG("IM notification policy with lime", im_notification_policy_with_lime, "LIME"), TEST_ONE_TAG("IM error delivery notification online", im_error_delivery_notification_online, "LIME"), @@ -2620,7 +2368,6 @@ test_t message_tests[] = { TEST_ONE_TAG("Lime transfer message without encryption", lime_transfer_message_without_encryption, "LIME"), TEST_ONE_TAG("Lime transfer message without encryption 2", lime_transfer_message_without_encryption_2, "LIME"), TEST_ONE_TAG("Lime unitary", lime_unit, "LIME"), -#ifdef SQLITE_STORAGE_ENABLED TEST_NO_TAG("Database migration", database_migration), TEST_NO_TAG("History range", history_range), TEST_NO_TAG("History count", history_count), @@ -2646,7 +2393,9 @@ test_t message_tests[] = { TEST_ONE_TAG("Real Time Text copy paste", real_time_text_copy_paste, "RTT"), TEST_NO_TAG("IM Encryption Engine custom headers", chat_message_custom_headers), TEST_NO_TAG("Text message with custom content-type", text_message_with_custom_content_type), +#ifdef SQLITE_STORAGE_ENABLED TEST_ONE_TAG("Text message with custom content-type and lime", text_message_with_custom_content_type_and_lime, "LIME"), +#endif TEST_NO_TAG("IM Encryption Engine XOR", im_encryption_engine_xor) }; From f7cc05300441de23f01ab63fc7faf4f71ba61d6a Mon Sep 17 00:00:00 2001 From: Johan Pascal Date: Mon, 3 Apr 2017 18:22:39 +0700 Subject: [PATCH 02/18] Add xml to sql zrtp/lime cache migration --- coreapi/linphonecore.c | 202 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 199 insertions(+), 3 deletions(-) diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 8c60c9b3f..85887d943 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -6186,6 +6186,202 @@ static void linphone_core_zrtp_cache_close(LinphoneCore *lc) { } #ifdef SQLITE_STORAGE_ENABLED +/* this function is called only when the sqlite cache is newly created but still empty(contains tables structures but no data) + * and we have an xml cache + * SQL zid cache associate each local sip:uri its own ZID while XML version used one ZID for the whole device-> use the XML provided ZID + * for the default local sipUri retrieved using linphone_core_get_identity + */ +static void linphone_core_zrtp_cache_migration(LinphoneCore *lc) { + FILE *CACHEFD = NULL; + /* load the xml cache */ + if (lc->zrtp_secrets_cache != NULL) { + CACHEFD = fopen(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"); + return; + } + cacheString[cacheSize] = '\0'; + cacheSize += 1; + fclose(CACHEFD); + cacheXml = xmlParseDoc((xmlChar*)cacheString); + ms_free(cacheString); + if (cacheXml) { + xmlNodePtr cur; + xmlChar *selfZidHex=NULL; + uint8_t selfZID[12]; + sqlite3 *db = (sqlite3 *)linphone_core_get_zrtp_cache_db(lc); + sqlite3_stmt *sqlStmt = NULL; + const char *selfURI = linphone_core_get_identity(lc); + int ret; + + /* parse the cache to get the selfZID and insert it in sqlcache */ + cur = xmlDocGetRootElement(cacheXml); + /* if we found a root element, parse its children node */ + if (cur!=NULL) + { + cur = cur->xmlChildrenNode; + } + selfZidHex = NULL; + while (cur!=NULL) { + if ((!xmlStrcmp(cur->name, (const xmlChar *)"selfZID"))){ /* self ZID found, extract it */ + selfZidHex = xmlNodeListGetString(cacheXml, cur->xmlChildrenNode, 1); + bctbx_strToUint8(selfZID, selfZidHex, 24); + break; + } + cur = cur->next; + } + /* did we found a self ZID? */ + if (selfZidHex == NULL) { + ms_warning("ZRTP/LIME cache migration: Failed to parse selfZID"); + return; + } + + /* insert the selfZID in cache, associate it to default local sip:uri in case we have more than one */ + ms_message("ZRTP/LIME cache migration: found selfZID %.24s link it to default URI %s in SQL cache", selfZidHex, selfURI); + xmlFree(selfZidHex); + + ret = sqlite3_prepare_v2(db, "INSERT INTO ziduri (zid,selfuri,peeruri) VALUES(?,?,?);", -1, &sqlStmt, NULL); + if (ret != SQLITE_OK) { + ms_warning("ZRTP/LIME cache migration: Failed to insert selfZID"); + return; + } + sqlite3_bind_blob(sqlStmt, 1, selfZID, 12, SQLITE_TRANSIENT); + sqlite3_bind_text(sqlStmt, 2, selfURI,-1,SQLITE_TRANSIENT); + sqlite3_bind_text(sqlStmt, 3, "self",-1,SQLITE_TRANSIENT); + + ret = sqlite3_step(sqlStmt); + if (ret!=SQLITE_DONE) { + ms_warning("ZRTP/LIME cache migration: Failed to insert selfZID"); + return; + } + sqlite3_finalize(sqlStmt); + + /* loop over all the peer node in the xml cache and get from them : uri(can be more than one), ZID, rs1, rs2, pvs, sndKey, rcvKey, sndSId, rcvSId, sndIndex, rcvIndex, valid */ + /* some of these may be missing(pvs, valid, rs2) but we'll consider them NULL */ + /* aux and pbx secrets were not used, so don't even bother looking for them */ + cur = xmlDocGetRootElement(cacheXml)->xmlChildrenNode; + + while (cur!=NULL) { /* loop on all peer nodes */ + if ((!xmlStrcmp(cur->name, (const xmlChar *)"peer"))) { /* found a peer node, check if there is a sipURI node in it (other nodes are just ignored) */ + int i; + xmlNodePtr peerNodeChildren = cur->xmlChildrenNode; + xmlChar *nodeContent = NULL; + xmlChar *peerZIDString = NULL; + uint8_t peerZID[12]; + uint8_t peerZIDFound=0; + xmlChar *peerUri[128]; /* array to contain all the peer uris found in one node */ + /* hopefully they won't be more than 128(it would mean some peer has more than 128 accounts and we called all of them...) */ + int peerUriIndex=0; /* index of previous array */ + char *zrtpColNames[] = {"rs1", "rs2", "pvs"}; + uint8_t *zrtpColValues[] = {NULL, NULL, NULL}; + size_t zrtpColExpectedLengths[] = {32,32,1}; + size_t zrtpColLengths[] = {0,0,0}; + + char *limeColNames[] = {"sndKey", "rcvKey", "sndSId", "rcvSId", "sndIndex", "rcvIndex", "valid"}; + uint8_t *limeColValues[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL}; + size_t limeColExpectedLengths[] = {32,32,32,32,4,4,8}; + size_t limeColLengths[] = {0,0,0,0,0,0,0}; + + /* check all the children nodes to retrieve all information we may get */ + while (peerNodeChildren!=NULL && peerUriIndex<128) { + if (!xmlStrcmp(peerNodeChildren->name, (const xmlChar *)"uri")) { /* found a peer an URI node, get the content */ + peerUri[peerUriIndex] = xmlNodeListGetString(cacheXml, peerNodeChildren->xmlChildrenNode, 1); + peerUriIndex++; + } + + if (!xmlStrcmp(peerNodeChildren->name, (const xmlChar *)"ZID")) { + peerZIDString = xmlNodeListGetString(cacheXml, peerNodeChildren->xmlChildrenNode, 1); + bctbx_strToUint8(peerZID, peerZIDString, 24); + + peerZIDFound=1; + } + + for (i=0; i<3; i++) { + if (!xmlStrcmp(peerNodeChildren->name, (const xmlChar *)zrtpColNames[i])) { + nodeContent = xmlNodeListGetString(cacheXml, peerNodeChildren->xmlChildrenNode, 1); + zrtpColValues[i] = (uint8_t *)bctbx_malloc(zrtpColExpectedLengths[i]); + bctbx_strToUint8(zrtpColValues[i], nodeContent, 2*zrtpColExpectedLengths[i]); + zrtpColLengths[i]=zrtpColExpectedLengths[i]; + } + } + + for (i=0; i<7; i++) { + if (!xmlStrcmp(peerNodeChildren->name, (const xmlChar *)limeColNames[i])) { + nodeContent = xmlNodeListGetString(cacheXml, peerNodeChildren->xmlChildrenNode, 1); + limeColValues[i] = (uint8_t *)bctbx_malloc(limeColExpectedLengths[i]); + bctbx_strToUint8(limeColValues[i], nodeContent, 2*limeColExpectedLengths[i]); + limeColLengths[i]=limeColExpectedLengths[i]; + } + } + + peerNodeChildren = peerNodeChildren->next; + xmlFree(nodeContent); + nodeContent=NULL; + } + + if (peerUriIndex>0 && peerZIDFound==1) { /* we found at least an uri in this peer node, extract the keys all other informations */ + /* retrieve all the informations */ + + /* loop over all the uri founds */ + for (i=0; inext; + } + } + } + } +} + + static void linphone_core_zrtp_cache_db_init(LinphoneCore *lc) { int ret; const char *errmsg; @@ -6210,12 +6406,12 @@ static void linphone_core_zrtp_cache_db_init(LinphoneCore *lc) { _linphone_sqlite3_open(lc->zrtp_cache_db_file, &db); } + lc->zrtp_cache_db = db; + if (ret == BZRTP_CACHE_SETUP && lc->zrtp_secrets_cache != NULL) { /* we just created the db and we have an old XML version of the cache : migrate */ - /* TODO */ + linphone_core_zrtp_cache_migration(lc); } - - lc->zrtp_cache_db = db; } #else /* SQLITE_STORAGE_ENABLED */ static void linphone_core_zrtp_cache_db_init(LinphoneCore *lc) { From e9a458d9aeabab348df8a3f955733c48a66fe1ad Mon Sep 17 00:00:00 2001 From: Johan Pascal Date: Thu, 6 Apr 2017 10:50:44 +0700 Subject: [PATCH 03/18] update mediastreamer2 and oRTP --- mediastreamer2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mediastreamer2 b/mediastreamer2 index be0bc9cce..fabdcf667 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit be0bc9ccef8c8f13665f3b1acec3298b3e4e1235 +Subproject commit fabdcf6671a90b93b6ce3865e7d34758ca875f33 From 1e105aec71ed44ca69c8556383e3f0b99a7eeecd Mon Sep 17 00:00:00 2001 From: Johan Pascal Date: Thu, 6 Apr 2017 13:19:19 +0700 Subject: [PATCH 04/18] update ms2 --- mediastreamer2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mediastreamer2 b/mediastreamer2 index fabdcf667..5e5d74bee 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit fabdcf6671a90b93b6ce3865e7d34758ca875f33 +Subproject commit 5e5d74beedd27a7fa06ed3c5fb27949fbaaf80ca From 10090bd63c63406aabed6ec86fefa135ba465188 Mon Sep 17 00:00:00 2001 From: Johan Pascal Date: Thu, 6 Apr 2017 14:16:20 +0700 Subject: [PATCH 05/18] update ortp --- oRTP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oRTP b/oRTP index 67c0672e2..8e6ab4f17 160000 --- a/oRTP +++ b/oRTP @@ -1 +1 @@ -Subproject commit 67c0672e2680baa85a74d8966b813fac259649df +Subproject commit 8e6ab4f17f8d1d6870859ba9c64157693d6537a1 From c72fca89532c04e4ab605e154dae1aff0d446e39 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Thu, 6 Apr 2017 15:11:31 +0200 Subject: [PATCH 06/18] Improve linphone config handling to prevent useless config file rewrite. --- coreapi/lpconfig.c | 27 +++++++++++++++------------ include/linphone/lpconfig.h | 2 +- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/coreapi/lpconfig.c b/coreapi/lpconfig.c index 296b0fb73..86c39e46c 100644 --- a/coreapi/lpconfig.c +++ b/coreapi/lpconfig.c @@ -87,8 +87,8 @@ struct _LpConfig{ char *filename; char *tmpfilename; bctbx_list_t *sections; - int modified; - int readonly; + bool_t modified; + bool_t readonly; bctbx_vfs_t* g_bctbx_vfs; }; @@ -443,7 +443,7 @@ static int _linphone_config_init_from_files(LinphoneConfig *lpconfig, const char linphone_config_parse(lpconfig, lpconfig->pFile); bctbx_file_close(lpconfig->pFile); lpconfig->pFile = NULL; - lpconfig->modified=0; + lpconfig->modified = FALSE; } } if (factory_config_filename != NULL) { @@ -655,9 +655,12 @@ void linphone_config_set_string(LpConfig *lpconfig,const char *section, const ch if (sec!=NULL){ item=lp_section_find_item(sec,key); if (item!=NULL){ - if (value!=NULL && value[0] != '\0') - lp_item_set_value(item,value); - else lp_section_remove_item(sec,item); + if ((value != NULL) && (value[0] != '\0')) { + if (strcmp(value, item->value) == 0) return; + lp_item_set_value(item, value); + } else { + lp_section_remove_item(sec, item); + } }else{ if (value!=NULL && value[0] != '\0') lp_section_add_item(sec,lp_item_new(key,value)); @@ -667,7 +670,7 @@ void linphone_config_set_string(LpConfig *lpconfig,const char *section, const ch linphone_config_add_section(lpconfig,sec); lp_section_add_item(sec,lp_item_new(key,value)); } - lpconfig->modified++; + lpconfig->modified = TRUE; } void linphone_config_set_string_list(LpConfig *lpconfig, const char *section, const char *key, const bctbx_list_t *value) { @@ -805,7 +808,7 @@ int linphone_config_sync(LpConfig *lpconfig){ lpconfig->pFile = pFile; if (pFile == NULL){ ms_warning("Could not write %s ! Maybe it is read-only. Configuration will not be saved.",lpconfig->filename); - lpconfig->readonly=1; + lpconfig->readonly = TRUE; return -1; } @@ -822,7 +825,7 @@ int linphone_config_sync(LpConfig *lpconfig){ if (rename(lpconfig->tmpfilename,lpconfig->filename)!=0){ ms_error("Cannot rename %s into %s: %s",lpconfig->tmpfilename,lpconfig->filename,strerror(errno)); } - lpconfig->modified=0; + lpconfig->modified = FALSE; return 0; } @@ -858,11 +861,11 @@ void linphone_config_clean_section(LpConfig *lpconfig, const char *section){ if (sec!=NULL){ linphone_config_remove_section(lpconfig,sec); } - lpconfig->modified++; + lpconfig->modified = TRUE; } -int linphone_config_needs_commit(const LpConfig *lpconfig){ - return lpconfig->modified>0; +bool_t linphone_config_needs_commit(const LpConfig *lpconfig){ + return lpconfig->modified; } static const char *DEFAULT_VALUES_SUFFIX = "_default_values"; diff --git a/include/linphone/lpconfig.h b/include/linphone/lpconfig.h index a76a1580e..1acd25104 100644 --- a/include/linphone/lpconfig.h +++ b/include/linphone/lpconfig.h @@ -217,7 +217,7 @@ void linphone_config_for_each_section(const LinphoneConfig *lpconfig, void (*cal void linphone_config_for_each_entry(const LinphoneConfig *lpconfig, const char *section, void (*callback)(const char *entry, void *ctx), void *ctx); /*tells whether uncommited (with linphone_config_sync()) modifications exist*/ -int linphone_config_needs_commit(const LinphoneConfig *lpconfig); +bool_t linphone_config_needs_commit(const LinphoneConfig *lpconfig); LINPHONE_PUBLIC void linphone_config_destroy(LinphoneConfig *cfg); From bcc1305863186234746fd91487495773db93a511 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Thu, 6 Apr 2017 17:22:18 +0200 Subject: [PATCH 07/18] fix x86_64 build --- coreapi/message_storage.c | 4 ++-- coreapi/sqlite3_bctbx_vfs.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/coreapi/message_storage.c b/coreapi/message_storage.c index 305900c1d..211230b76 100644 --- a/coreapi/message_storage.c +++ b/coreapi/message_storage.c @@ -28,7 +28,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #endif #ifndef _WIN32 -#if !defined(__QNXNTO__) && !(defined(__ANDROID__) && defined(__LP64__)) +#if !defined(__QNXNTO__) && !defined(__ANDROID__) #include #include #include @@ -51,7 +51,7 @@ static char *utf8_convert(const char *filename){ wchar_t db_file_utf16[MAX_PATH_SIZE]={0}; MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, filename, -1, db_file_utf16, MAX_PATH_SIZE); WideCharToMultiByte(CP_UTF8, 0, db_file_utf16, -1, db_file_utf8, sizeof(db_file_utf8), NULL, NULL); -#elif defined(__QNXNTO__) || (defined(__ANDROID__) && defined(__LP64__)) +#elif defined(__QNXNTO__) || defined(__ANDROID__) strncpy(db_file_utf8, filename, MAX_PATH_SIZE - 1); #else char db_file_locale[MAX_PATH_SIZE] = {'\0'}; diff --git a/coreapi/sqlite3_bctbx_vfs.c b/coreapi/sqlite3_bctbx_vfs.c index 9b8b1b452..e5674e43e 100755 --- a/coreapi/sqlite3_bctbx_vfs.c +++ b/coreapi/sqlite3_bctbx_vfs.c @@ -29,7 +29,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #ifndef _WIN32 -#if !defined(__QNXNTO__) && !(defined(__ANDROID__) && defined(__LP64__)) +#if !defined(__QNXNTO__) && !defined(__ANDROID__) # include # include # include @@ -281,7 +281,7 @@ static char* ConvertFromUtf8Filename(const char* fName){ } bctbx_free(wideFilename); return convertedFilename; -#elif defined(__QNXNTO__) || (defined(__ANDROID__) && defined(__LP64__)) +#elif defined(__QNXNTO__) || defined(__ANDROID__) return bctbx_strdup(fName); #else #define MAX_PATH_SIZE 1024 From 1cf68854463d49217ce5aa38bc50f7e6acfd96f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Grisez?= Date: Thu, 6 Apr 2017 17:34:22 +0200 Subject: [PATCH 08/18] Disable the compilation of lp-gen-wrapper with autotools --- tools/Makefile.am | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/tools/Makefile.am b/tools/Makefile.am index afcc52cdb..2531b7b3a 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -20,7 +20,7 @@ EXTRA_DIST=xml2lpc_jni.cc lpc2xml_jni.cc if BUILD_TOOLS -bin_PROGRAMS=xml2lpc_test lpc2xml_test lp-gen-wrappers lp-autoanswer lp-test-ecc lp-sendmsg +bin_PROGRAMS=xml2lpc_test lpc2xml_test lp-autoanswer lp-test-ecc lp-sendmsg xml2lpc_test_SOURCES=\ xml2lpc_test.c @@ -36,13 +36,6 @@ lpc2xml_test_CFLAGS=$(COMMON_CFLAGS) lpc2xml_test_LDADD=\ $(top_builddir)/coreapi/liblinphone.la -lp_gen_wrappers_SOURCES=genwrappers.cc \ - software-desc.cc software-desc.hh \ - generator.cc generator.hh - -lp_gen_wrappers_LDADD= \ - $(LIBXML2_LIBS) - lp_autoanswer_SOURCES=auto_answer.c lp_autoanswer_CFLAGS=$(COMMON_CFLAGS) lp_autoanswer_LDADD=\ From cb4fcaeb312d592405b725327639c8c6cba4050d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Grisez?= Date: Fri, 7 Apr 2017 09:08:06 +0200 Subject: [PATCH 09/18] Remove lp-gen-wrapper from the RPM spec file --- linphone.spec.in | 1 - 1 file changed, 1 deletion(-) diff --git a/linphone.spec.in b/linphone.spec.in index d0a721233..2bd2843d8 100644 --- a/linphone.spec.in +++ b/linphone.spec.in @@ -101,7 +101,6 @@ rm -rf $RPM_BUILD_ROOT %defattr(-,root,root) %{_bindir}/lpc2xml_test %{_bindir}/xml2lpc_test -%{_bindir}/lp-gen-wrappers %{_bindir}/lp-sendmsg %{_includedir}/linphone %{_libdir}/*.a From 3bd323bec3535cb599d523096b49dced43f16308 Mon Sep 17 00:00:00 2001 From: Brieuc Viel Date: Fri, 7 Apr 2017 10:48:56 +0200 Subject: [PATCH 10/18] [JNI] remove listener unregistration on LinphoneMessageState = NotDelivered --- coreapi/linphonecore_jni.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/coreapi/linphonecore_jni.cc b/coreapi/linphonecore_jni.cc index 9a40acbc7..99141e869 100644 --- a/coreapi/linphonecore_jni.cc +++ b/coreapi/linphonecore_jni.cc @@ -4575,7 +4575,7 @@ extern "C" jboolean Java_org_linphone_core_LinphoneChatMessageImpl_isSecured(JNI return linphone_chat_message_is_secured((LinphoneChatMessage*)ptr); } -extern "C" void Java_org_linphone_core_LinphoneChatMessageImpl_resend(JNIEnv* env +extern "C" void Java_org_linphone_core_LinphoneChatMessageImpl_reSend(JNIEnv* env ,jobject thiz ,jlong ptr) { linphone_chat_message_resend((LinphoneChatMessage*)ptr); @@ -4605,7 +4605,7 @@ static void message_state_changed(LinphoneChatMessage* msg, LinphoneChatMessageS LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc); env->CallVoidMethod(listener, method, jmessage, env->CallStaticObjectMethod(ljb->chatMessageStateClass, ljb->chatMessageStateFromIntId, (jint)state)); - if (state == LinphoneChatMessageStateDisplayed || state == LinphoneChatMessageStateNotDelivered) { + if (state == LinphoneChatMessageStateDisplayed) { env->DeleteGlobalRef(listener); msg->message_state_changed_user_data = NULL; } @@ -4768,7 +4768,7 @@ static void chat_room_impl_callback(LinphoneChatMessage* msg, LinphoneChatMessag jmessage, env->CallStaticObjectMethod(ljb->chatMessageStateClass,ljb->chatMessageStateFromIntId,(jint)state)); - if (state == LinphoneChatMessageStateDisplayed || state == LinphoneChatMessageStateNotDelivered) { + if (state == LinphoneChatMessageStateDisplayed ) { env->DeleteGlobalRef(listener); env->DeleteGlobalRef(jmessage); linphone_chat_message_set_user_data(msg,NULL); From bfcda8ef5dae3297ed13e6485f6a85fff3e89a46 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Fri, 7 Apr 2017 14:20:16 +0200 Subject: [PATCH 11/18] Fix build on Windows. --- coreapi/payload_type.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreapi/payload_type.c b/coreapi/payload_type.c index 3584b49c3..e53d0739f 100644 --- a/coreapi/payload_type.c +++ b/coreapi/payload_type.c @@ -29,7 +29,7 @@ struct _LinphonePayloadType { }; BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphonePayloadType); -BELLE_SIP_DECLARE_VPTR(LinphonePayloadType); +BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphonePayloadType); LinphonePayloadType *linphone_payload_type_new(LinphoneCore *lc, OrtpPayloadType *ortp_pt) { LinphonePayloadType *pt; From cc08579621677e9b4403529656cf2e90d43db961 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Fri, 7 Apr 2017 14:58:26 +0200 Subject: [PATCH 12/18] avoid strcpy() --- coreapi/bellesip_sal/sal_op_call.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c index 86c5460ee..9676c9b73 100644 --- a/coreapi/bellesip_sal/sal_op_call.c +++ b/coreapi/bellesip_sal/sal_op_call.c @@ -37,11 +37,11 @@ static void call_set_error(SalOp* op,belle_sip_response_t* response, bool_t fata if (fatal) op->state = SalOpStateTerminating; op->base.root->callbacks.call_failure(op); } -static void set_addr_to_0000(char value[]) { +static void set_addr_to_0000(char value[], size_t sz) { if (ms_is_ipv6(value)) { - strcpy(value,"::0"); + strncpy(value,"::0", sz); } else { - strcpy(value,"0.0.0.0"); + strncpy(value,"0.0.0.0", sz); } return; } @@ -66,11 +66,11 @@ static void sdp_process(SalOp *h){ offer_answer_initiate_incoming(h->base.root->factory, h->base.local_media,h->base.remote_media,h->result,h->base.root->one_matching_codec); /*for backward compatibility purpose*/ if(h->cnx_ip_to_0000_if_sendonly_enabled && sal_media_description_has_dir(h->result,SalStreamSendOnly)) { - set_addr_to_0000(h->result->addr); + set_addr_to_0000(h->result->addr, sizeof(h->result->addr)); for(i=0;iresult->streams[i].dir == SalStreamSendOnly) { - set_addr_to_0000(h->result->streams[i].rtp_addr); - set_addr_to_0000(h->result->streams[i].rtcp_addr); + set_addr_to_0000(h->result->streams[i].rtp_addr, sizeof(h->result->streams[i].rtp_addr)); + set_addr_to_0000(h->result->streams[i].rtcp_addr, sizeof(h->result->streams[i].rtcp_addr)); } } } From fc12b101a870fa0170a5bda11b4202e0281d708b Mon Sep 17 00:00:00 2001 From: Ronan Abhamon Date: Mon, 10 Apr 2017 13:35:08 +0200 Subject: [PATCH 13/18] feat(account_creator): provide a reset function --- coreapi/account_creator.c | 52 ++++++++++++++++++------------ include/linphone/account_creator.h | 7 ++++ 2 files changed, 39 insertions(+), 20 deletions(-) diff --git a/coreapi/account_creator.c b/coreapi/account_creator.c index 0c6a3abd8..3c65d4fff 100644 --- a/coreapi/account_creator.c +++ b/coreapi/account_creator.c @@ -292,17 +292,7 @@ static void _linphone_account_creator_destroy(LinphoneAccountCreator *creator) { linphone_account_creator_service_get_destructor_cb(creator->service)(creator); linphone_account_creator_cbs_unref(creator->cbs); linphone_proxy_config_unref(creator->proxy_cfg); - if (creator->username) ms_free(creator->username); - if (creator->display_name) ms_free(creator->display_name); - if (creator->password) ms_free(creator->password); - if (creator->ha1) ms_free(creator->ha1); - if (creator->phone_number) ms_free(creator->phone_number); - if (creator->phone_country_code) ms_free(creator->phone_country_code); - if (creator->email) ms_free(creator->email); - if (creator->language) ms_free(creator->language); - if (creator->activation_code) ms_free(creator->activation_code); - if (creator->domain) ms_free(creator->domain); - if (creator->route) ms_free(creator->route); + linphone_account_creator_reset(creator); } BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneAccountCreator); @@ -335,6 +325,28 @@ LinphoneAccountCreator * linphone_account_creator_new(LinphoneCore *core, const return _linphone_account_creator_new(core, xmlrpc_url); } +#define _reset_field(field) \ + if (field) { \ + ms_free(field); \ + field = NULL; \ + } + +void linphone_account_creator_reset(LinphoneAccountCreator *creator) { + _reset_field(creator->username); + _reset_field(creator->display_name); + _reset_field(creator->password); + _reset_field(creator->ha1); + _reset_field(creator->phone_number); + _reset_field(creator->phone_country_code); + _reset_field(creator->email); + _reset_field(creator->language); + _reset_field(creator->activation_code); + _reset_field(creator->domain); + _reset_field(creator->route); +} + +#undef _reset_field + LinphoneAccountCreator * linphone_core_create_account_creator(LinphoneCore *core, const char *xmlrpc_url) { return _linphone_account_creator_new(core, xmlrpc_url); } @@ -934,19 +946,19 @@ static void _get_phone_number_for_account_cb_custom(LinphoneXmlRpcRequest *reque } LinphoneAccountCreatorStatus linphone_account_creator_is_account_linked_linphone(LinphoneAccountCreator *creator) { - LinphoneXmlRpcRequest *request; - if (!creator->username || !linphone_proxy_config_get_domain(creator->proxy_cfg)) { + LinphoneXmlRpcRequest *request; + if (!creator->username || !linphone_proxy_config_get_domain(creator->proxy_cfg)) { return LinphoneAccountCreatorStatusMissingArguments; - } - request = linphone_xml_rpc_request_new_with_args(LinphoneXmlRpcArgString, "get_phone_number_for_account", + } + request = linphone_xml_rpc_request_new_with_args(LinphoneXmlRpcArgString, "get_phone_number_for_account", LinphoneXmlRpcArgString, creator->username, LinphoneXmlRpcArgString, linphone_proxy_config_get_domain(creator->proxy_cfg), LinphoneXmlRpcArgNone); - linphone_xml_rpc_request_set_user_data(request, creator); - linphone_xml_rpc_request_cbs_set_response(linphone_xml_rpc_request_get_callbacks(request), _get_phone_number_for_account_cb_custom); - linphone_xml_rpc_session_send_request(creator->xmlrpc_session, request); - linphone_xml_rpc_request_unref(request); - return LinphoneAccountCreatorStatusRequestOk; + linphone_xml_rpc_request_set_user_data(request, creator); + linphone_xml_rpc_request_cbs_set_response(linphone_xml_rpc_request_get_callbacks(request), _get_phone_number_for_account_cb_custom); + linphone_xml_rpc_session_send_request(creator->xmlrpc_session, request); + linphone_xml_rpc_request_unref(request); + return LinphoneAccountCreatorStatusRequestOk; } /****************** END OF LINK PHONE NUMBER WITH ACCOUNT SECTION *************/ diff --git a/include/linphone/account_creator.h b/include/linphone/account_creator.h index 14f0f3ca9..a4bfca7c4 100644 --- a/include/linphone/account_creator.h +++ b/include/linphone/account_creator.h @@ -48,6 +48,13 @@ typedef void (*LinphoneAccountCreatorCbsStatusCb)(LinphoneAccountCreator *creato **/ LINPHONE_PUBLIC LinphoneAccountCreator * linphone_account_creator_new(LinphoneCore *core, const char *xmlrpc_url); + +/** + * Reset the account creator entries like username, password, phone number... + * @param[in] creator LinphoneAccountCreator object +**/ +LINPHONE_PUBLIC void linphone_account_creator_reset(LinphoneAccountCreator *creator); + /** * Send a request to know the existence of account on server. * @param[in] creator LinphoneAccountCreator object From a3fbb53b246b53f5c19a5a8a6a0b9f7947e9d970 Mon Sep 17 00:00:00 2001 From: Ronan Abhamon Date: Mon, 10 Apr 2017 13:40:46 +0200 Subject: [PATCH 14/18] feat(account_creator): set_email deals with undefined email --- coreapi/account_creator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreapi/account_creator.c b/coreapi/account_creator.c index 3c65d4fff..34dbfd24c 100644 --- a/coreapi/account_creator.c +++ b/coreapi/account_creator.c @@ -505,7 +505,7 @@ const char * linphone_account_creator_get_display_name(const LinphoneAccountCrea } LinphoneAccountCreatorEmailStatus linphone_account_creator_set_email(LinphoneAccountCreator *creator, const char *email) { - if (!is_matching_regex(email, "^.+@.+\\..*$")) { + if (!email || !is_matching_regex(email, "^.+@.+\\..*$")) { return LinphoneAccountCreatorEmailStatusMalformed; } if (!is_matching_regex(email, "^.+@.+\\.[A-Za-z]{2}[A-Za-z]*$")) { From 1dbb7f54095b83a35df747ee73115c38b19e965f Mon Sep 17 00:00:00 2001 From: Erwan Croze Date: Mon, 10 Apr 2017 13:42:11 +0200 Subject: [PATCH 15/18] Add new call status "EarlyAborted" --- .../org/linphone/core/LinphoneCallLog.java | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/java/common/org/linphone/core/LinphoneCallLog.java b/java/common/org/linphone/core/LinphoneCallLog.java index 224da73f7..4100a856b 100644 --- a/java/common/org/linphone/core/LinphoneCallLog.java +++ b/java/common/org/linphone/core/LinphoneCallLog.java @@ -18,7 +18,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package org.linphone.core; /** - * Call data records object + * Call data records object * */ import java.util.Vector; @@ -35,14 +35,14 @@ public interface LinphoneCallLog { * */ static class CallStatus { - + static private Vector values = new Vector(); private final int mValue; private final String mStringValue; /** * Call success. */ - public final static CallStatus Success = new CallStatus(0,"Sucess"); + public final static CallStatus Success = new CallStatus(0,"Success"); /** * Call aborted. */ @@ -55,8 +55,13 @@ public interface LinphoneCallLog { * remote call declined. */ public final static CallStatus Declined = new CallStatus(3,"Declined"); - - + + /** + * The call was aborted before being advertised to the application - for protocol reasons + */ + public final static CallStatus EarlyAborted = new CallStatus(4,"Early Aborted"); + + private CallStatus(int value,String stringValue) { mValue = value; values.addElement(this); @@ -77,7 +82,7 @@ public interface LinphoneCallLog { return mValue; } } - + /** * Originator of the call as a LinphoneAddress object. * @return LinphoneAddress @@ -98,19 +103,19 @@ public interface LinphoneCallLog { * @return CallStatus */ public CallStatus getStatus(); - + /** * A human readable String with the start date/time of the call * @return String */ public String getStartDate(); - + /** * A timestamp of the start date/time of the call in milliseconds since January 1st 1970 * @return long */ public long getTimestamp(); - + /** * The call duration, in seconds * @return int From 44b2f6ada7b034511c8a23d4dd255bf573b0f1f9 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Tue, 11 Apr 2017 10:41:16 +0200 Subject: [PATCH 16/18] Fix call logs read from database clearing in migration process. --- coreapi/call_log.c | 7 +++++-- coreapi/linphonecore.c | 17 +++++++++-------- coreapi/private.h | 2 +- tester/call_single_tester.c | 2 +- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/coreapi/call_log.c b/coreapi/call_log.c index 6e9184f77..99ad154da 100644 --- a/coreapi/call_log.c +++ b/coreapi/call_log.c @@ -116,12 +116,14 @@ void call_logs_write_to_config_file(LinphoneCore *lc){ } } -void call_logs_read_from_config_file(LinphoneCore *lc){ +bctbx_list_t * call_logs_read_from_config_file(LinphoneCore *lc){ char logsection[32]; int i; const char *tmp; uint64_t sec; LpConfig *cfg=lc->config; + bctbx_list_t *call_logs; + for(i=0;;++i){ snprintf(logsection,sizeof(logsection),"call_log_%i",i); if (lp_config_has_section(cfg,logsection)){ @@ -154,9 +156,10 @@ void call_logs_read_from_config_file(LinphoneCore *lc){ cl->video_enabled=lp_config_get_int(cfg,logsection,"video_enabled",0); tmp=lp_config_get_string(cfg,logsection,"call_id",NULL); if (tmp) cl->call_id=ms_strdup(tmp); - lc->call_logs=bctbx_list_append(lc->call_logs,cl); + call_logs=bctbx_list_append(call_logs,cl); }else break; } + return call_logs; } diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index a7af0c675..e08ef3413 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -1730,13 +1730,15 @@ static void ui_config_read(LinphoneCore *lc) { #ifndef SQLITE_STORAGE_ENABLED read_friends_from_rc(lc); + lc->call_logs = call_logs_read_from_config_file(lc); #else if (!lc->friends_db) { read_friends_from_rc(lc); } + if (!lc->logs_db) { + lc->call_logs = call_logs_read_from_config_file(lc); + } #endif - - call_logs_read_from_config_file(lc); } /* @@ -4624,17 +4626,16 @@ void linphone_core_migrate_logs_from_rc_to_db(LinphoneCore *lc) { return; } - // This is because there must have been a call previously to linphone_core_call_log_storage_init - lc->call_logs = bctbx_list_free_with_data(lc->call_logs, (void (*)(void*))linphone_call_log_unref); - - call_logs_read_from_config_file(lc); - if (!lc->call_logs) { + logs_to_migrate = call_logs_read_from_config_file(lc); + if (!logs_to_migrate) { ms_warning("nothing to migrate, skipping..."); return; } - logs_to_migrate = lc->call_logs; + // This is because there must have been a call previously to linphone_core_call_log_storage_init + lc->call_logs = bctbx_list_free_with_data(lc->call_logs, (void (*)(void*))linphone_call_log_unref); lc->call_logs = NULL; + // We can't use bctbx_list_for_each because logs_to_migrate are listed in the wrong order (latest first), and we want to store the logs latest last for (i = (int)bctbx_list_size(logs_to_migrate) - 1; i >= 0; i--) { LinphoneCallLog *log = (LinphoneCallLog *) bctbx_list_nth_data(logs_to_migrate, i); diff --git a/coreapi/private.h b/coreapi/private.h index 70f1f6820..b0c9d47e9 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -1254,7 +1254,7 @@ void _linphone_core_codec_config_write(LinphoneCore *lc); #endif #endif -LINPHONE_PUBLIC void call_logs_read_from_config_file(LinphoneCore *lc); +LINPHONE_PUBLIC bctbx_list_t * call_logs_read_from_config_file(LinphoneCore *lc); void call_logs_write_to_config_file(LinphoneCore *lc); void linphone_core_call_log_storage_init(LinphoneCore *lc); void linphone_core_call_log_storage_close(LinphoneCore *lc); diff --git a/tester/call_single_tester.c b/tester/call_single_tester.c index 2c08c73c5..991f28482 100644 --- a/tester/call_single_tester.c +++ b/tester/call_single_tester.c @@ -4898,7 +4898,7 @@ static void call_logs_migrate(void) { } laure->lc->call_logs = bctbx_list_free_with_data(laure->lc->call_logs, (void (*)(void*))linphone_call_log_unref); - call_logs_read_from_config_file(laure->lc); + laure->lc->call_logs = call_logs_read_from_config_file(laure->lc); BC_ASSERT_TRUE(bctbx_list_size(laure->lc->call_logs) == 0); unlink(logs_db); From aad3b7e30bba72ca7dbdbed746c66bb1f3fe0fd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Grisez?= Date: Tue, 11 Apr 2017 11:13:51 +0200 Subject: [PATCH 17/18] Fix bad call duration computation when the call has not passed by the Connected state --- coreapi/linphonecall.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index bd2bcc58f..322ef88d4 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -2181,23 +2181,20 @@ bool_t linphone_call_has_transfer_pending(const LinphoneCall *call){ return call->refer_pending; } -static int _linphone_call_get_duration (const LinphoneCall *call) { - return (int)(ms_time(NULL) - call->log->connected_date_time); +static int _linphone_call_compute_duration (const LinphoneCall *call) { + if (call->log->connected_date_time == 0) return 0; + else return (int)(ms_time(NULL) - call->log->connected_date_time); } -int linphone_call_get_duration(const LinphoneCall *call){ - if (call->log->connected_date_time==0) return 0; - +int linphone_call_get_duration(const LinphoneCall *call) { switch (call->state) { case LinphoneCallEnd: case LinphoneCallError: case LinphoneCallReleased: return call->log->duration; - - default: break; + default: + return _linphone_call_compute_duration(call); } - - return _linphone_call_get_duration(call); } LinphoneCall *linphone_call_get_replaced_call(LinphoneCall *call){ @@ -4694,7 +4691,7 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse void linphone_call_log_completed(LinphoneCall *call){ LinphoneCore *lc=call->core; - call->log->duration=_linphone_call_get_duration(call); /*store duration since connected*/ + call->log->duration= _linphone_call_compute_duration(call); /*store duration since connected*/ call->log->error_info = linphone_error_info_ref((LinphoneErrorInfo*)linphone_call_get_error_info(call)); if (call->log->status==LinphoneCallMissed){ From 145b15c2712c787f3d0129b7d643a4df5d1e6a2e Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Tue, 11 Apr 2017 11:47:49 +0200 Subject: [PATCH 18/18] Fix missing variable initialization. --- coreapi/call_log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreapi/call_log.c b/coreapi/call_log.c index 99ad154da..8c5f31154 100644 --- a/coreapi/call_log.c +++ b/coreapi/call_log.c @@ -122,7 +122,7 @@ bctbx_list_t * call_logs_read_from_config_file(LinphoneCore *lc){ const char *tmp; uint64_t sec; LpConfig *cfg=lc->config; - bctbx_list_t *call_logs; + bctbx_list_t *call_logs = NULL; for(i=0;;++i){ snprintf(logsection,sizeof(logsection),"call_log_%i",i);