Commit d4cbbbe0 authored by johan's avatar johan

Cache migration from xml to sql is now part of bzrtp lib

parent 4c37a23c
......@@ -57,6 +57,8 @@ endif()
if(ENABLE_ZIDCACHE)
find_package(Sqlite3 REQUIRED)
# Also check if we have libxml2, as we need it for migration purpose
find_package(XML2)
endif()
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h)
......@@ -98,6 +100,9 @@ endif()
if(ENABLE_ZIDCACHE)
add_definitions("-DZIDCACHE_ENABLED")
if(XML2_FOUND)
add_definitions("-DHAVE_LIBXML2")
endif()
endif()
......
############################################################################
# FindXML2.txt
# Copyright (C) 2015 Belledonne Communications, Grenoble France
#
############################################################################
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
############################################################################
#
# - Find the libxml2 include file and library
#
# XML2_FOUND - system has libxml2
# XML2_INCLUDE_DIRS - the libxml2 include directory
# XML2_LIBRARIES - The libraries needed to use libxml2
if(APPLE AND NOT IOS)
set(XML2_HINTS "/usr")
endif()
if(XML2_HINTS)
set(XML2_LIBRARIES_HINTS "${XML2_HINTS}/lib")
endif()
find_path(XML2_INCLUDE_DIRS
NAMES libxml/xmlreader.h
HINTS "${XML2_HINTS}"
PATH_SUFFIXES include/libxml2
)
if(XML2_INCLUDE_DIRS)
set(HAVE_LIBXML_XMLREADER_H 1)
endif()
find_library(XML2_LIBRARIES
NAMES xml2
HINTS "${XML2_LIBRARIES_HINTS}"
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(XML2
DEFAULT_MSG
XML2_INCLUDE_DIRS XML2_LIBRARIES
)
mark_as_advanced(XML2_INCLUDE_DIRS XML2_LIBRARIES)
......@@ -25,3 +25,4 @@
#cmakedefine HAVE_CU_CURSES
#cmakedefine ZIDCACHE_ENABLED
#cmakedefine HAVE_LIBXML2
......@@ -166,6 +166,7 @@ typedef struct bzrtpCallbacks_struct {
#define BZRTP_ERROR_HELLOHASH_MISMATCH 0x0080
#define BZRTP_ERROR_CHANNELALREADYSTARTED 0x0100
#define BZRTP_ERROR_CACHEDISABLED 0x0200
#define BZRTP_ERROR_CACHEMIGRATIONFAILED 0x0400
/* channel status definition */
#define BZRTP_CHANNEL_NOTFOUND 0x1000
......@@ -460,6 +461,18 @@ BZRTP_EXPORT int bzrtp_cache_write(void *dbPointer, int zuid, char *tableName, c
*/
BZRTP_EXPORT int bzrtp_cache_read(void *dbPointer, int zuid, char *tableName, char **columns, uint8_t **values, size_t *lengths, uint8_t columnsCount);
/**
* @brief Perform migration from xml version to sqlite3 version of cache
* Warning: new version of cache associate a ZID to each local URI, the old one did not
* the migration function will associate any data in the cache to the sip URI given in parameter which shall be the default URI
* @param[in] cacheXml a pointer to an xmlDocPtr structure containing the old cache to be migrated
* @param[in/out] cacheSqlite a pointer to an sqlite3 structure containing a cache initialised using bzrtp_cache_init function
* @param[in] selfURI default sip URI for this end point, NULL terminated char
*
* @return 0 on success, BZRTP_ERROR_CACHEDISABLED when bzrtp was not compiled with cache enabled, BZRTP_ERROR_CACHEMIGRATIONFAILED on error during migration
*/
BZRTP_EXPORT int bzrtp_cache_migration(void *cacheXmlPtr, void *cacheSqlite, const char *selfURI);
/*
* @brief Allow client to compute an exported according to RFC section 4.5.2
* Check the context is ready(we already have a master exported key and KDF context)
......
......@@ -42,6 +42,10 @@ if(SQLITE3_FOUND)
list(APPEND INCLUDE_DIRS ${SQLITE3_INCLUDE_DIRS})
list(APPEND LIBS ${SQLITE3_LIBRARIES})
endif()
if(XML2_FOUND)
list(APPEND INCLUDE_DIRS ${XML2_INCLUDE_DIRS})
list(APPEND LIBS ${XML2_LIBRARIES})
endif()
if(ENABLE_STATIC)
add_library(bzrtp-static STATIC ${SOURCE_FILES})
......
......@@ -33,6 +33,10 @@
#ifdef ZIDCACHE_ENABLED
#include "sqlite3.h"
#ifdef HAVE_LIBXML2
#include <libxml/tree.h>
#include <libxml/parser.h>
#endif /* HAVE_LIBXML2 */
#ifdef _WIN32
#include <malloc.h>
......@@ -624,6 +628,189 @@ int bzrtp_cache_read(void *dbPointer, int zuid, char *tableName, char **columns,
return 0;
}
/**
* @brief Perform migration from xml version to sqlite3 version of cache
* Warning: new version of cache associate a ZID to each local URI, the old one did not
* the migration function will associate any data in the cache to the sip URI given in parameter which shall be the default URI
* @param[in] cacheXml a pointer to an xmlDocPtr structure containing the old cache to be migrated
* @param[in/out] cacheSqlite a pointer to an sqlite3 structure containing a cache initialised using bzrtp_cache_init function
* @param[in] selfURI default sip URI for this end point, NULL terminated char
*
* @return 0 on success, BZRTP_ERROR_CACHEDISABLED when bzrtp was not compiled with cache enabled, BZRTP_ERROR_CACHEMIGRATIONFAILED on error during migration
*/
int bzrtp_cache_migration(void *cacheXmlPtr, void *cacheSqlite, const char *selfURI) {
if (cacheXmlPtr) {
xmlDocPtr cacheXml = (xmlDocPtr)cacheXmlPtr;
xmlNodePtr cur;
xmlChar *selfZidHex=NULL;
uint8_t selfZID[12];
sqlite3 *db = (sqlite3 *)cacheSqlite;
sqlite3_stmt *sqlStmt = NULL;
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_str_to_uint8(selfZID, selfZidHex, 24);
break;
}
cur = cur->next;
}
/* did we found a self ZID? */
if (selfZidHex == NULL) {
bctbx_warning("ZRTP/LIME cache migration: Failed to parse selfZID");
return BZRTP_ERROR_CACHEMIGRATIONFAILED;
}
/* insert the selfZID in cache, associate it to default local sip:uri in case we have more than one */
bctbx_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) {
bctbx_warning("ZRTP/LIME cache migration: Failed to insert selfZID");
return BZRTP_ERROR_CACHEMIGRATIONFAILED;
}
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) {
bctbx_warning("ZRTP/LIME cache migration: Failed to insert selfZID");
return BZRTP_ERROR_CACHEMIGRATIONFAILED;
}
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_str_to_uint8(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_str_to_uint8(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_str_to_uint8(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; i<peerUriIndex; i++) {
char *stmt = NULL;
int zuid;
/* create the entry in the ziduri table (it will give us the zuid to be used to insert infos in lime and zrtp tables) */
/* we could use directly the bzrtp_cache_getZuid function, but avoid useless query by directly inserting the data */
stmt = sqlite3_mprintf("INSERT INTO ziduri (zid,selfuri,peeruri) VALUES(?,?,?);");
ret = sqlite3_prepare_v2(db, stmt, -1, &sqlStmt, NULL);
if (ret != SQLITE_OK) {
bctbx_warning("ZRTP/LIME cache migration: Failed to insert peer ZID %s", peerUri[i]);
return BZRTP_ERROR_CACHEMIGRATIONFAILED;
}
sqlite3_free(stmt);
sqlite3_bind_blob(sqlStmt, 1, peerZID, 12, SQLITE_TRANSIENT);
sqlite3_bind_text(sqlStmt, 2, selfURI, -1, SQLITE_TRANSIENT);
sqlite3_bind_text(sqlStmt, 3, (const char *)(peerUri[i]), -1, SQLITE_TRANSIENT);
ret = sqlite3_step(sqlStmt);
if (ret!=SQLITE_DONE) {
bctbx_warning("ZRTP/LIME cache migration: Failed to insert peer ZID %s", peerUri[i]);
return BZRTP_ERROR_CACHEMIGRATIONFAILED;
}
sqlite3_finalize(sqlStmt);
/* get the zuid created */
zuid = (int)sqlite3_last_insert_rowid(db);
bctbx_message("ZRTP/LIME cache migration: Inserted self %s peer %s ZID %s sucessfully with zuid %d\n", selfURI, peerUri[i], peerZIDString, zuid);
xmlFree(peerUri[i]);
peerUri[i]=NULL;
/* now insert data in the zrtp and lime table, keep going even if it fails */
if ((ret=bzrtp_cache_write(db, zuid, "zrtp", zrtpColNames, zrtpColValues, zrtpColLengths, 3)) != 0) {
bctbx_error("ZRTP/LIME cache migration: could not insert data in zrtp table, return value %x", ret);
}
if ((ret=bzrtp_cache_write(db, zuid, "lime", limeColNames, limeColValues, limeColLengths, 7)) != 0) {
bctbx_error("ZRTP/LIME cache migration: could not insert data in lime table, return value %x", ret);
}
}
}
bctbx_free(zrtpColValues[0]);
bctbx_free(zrtpColValues[1]);
bctbx_free(zrtpColValues[2]);
for (i=0; i<7; i++) {
bctbx_free(limeColValues[i]);
}
xmlFree(peerZIDString);
}
cur = cur->next;
}
return 0;
}
return BZRTP_ERROR_CACHEMIGRATIONFAILED;
}
#else /* ZIDCACHE_ENABLED */
int bzrtp_getSelfZID(void *dbPointer, const char *selfURI, uint8_t selfZID[12], bctbx_rng_context_t *RNGContext) {
......@@ -666,4 +853,8 @@ int bzrtp_cache_write(void *dbPointer, int zuid, char *tableName, char **columns
int bzrtp_cache_read(void *dbPointer, int zuid, char *tableName, char **columns, uint8_t **values, size_t *lengths, uint8_t columnsCount) {
return BZRTP_ERROR_CACHEDISABLED;
}
int bzrtp_cache_migration(xmlDocPtr cacheXml, void *cacheSqlite, const char *selfURI) {
return BZRTP_ERROR_CACHEDISABLED;
}
#endif /* ZIDCACHE_ENABLED */
......@@ -44,6 +44,9 @@ target_link_libraries(bzrtpTest ${BCTOOLBOX_LIBRARIES})
if(SQLITE3_FOUND)
target_include_directories(bzrtpTest PUBLIC ${SQLITE3_INCLUDE_DIRS})
target_link_libraries(bzrtpTest ${SQLITE3_LIBRARIES})
if(XML2_FOUND)
target_link_libraries(bzrtpTest ${XML2_LIBRARIES})
endif()
endif()
if(HAVE_SQRT)
target_link_libraries(bzrtpTest m)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment