From fcc61d1aa5727d5bffb08cfd58cefadf02ef31fa Mon Sep 17 00:00:00 2001 From: Johan Pascal Date: Sat, 1 Apr 2017 11:05:08 +0700 Subject: [PATCH 1/5] 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 2/5] 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 3/5] 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 4/5] 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 5/5] 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