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) {