static mlist_t mitmcache_head;
static uint32_t g_mitmcache_elems_counter = 0;
static uint8_t inited = 0;
+static uint8_t g_needs_rewriting = 0;
static zrtp_global_t* zrtp;
static zrtp_mutex_t* def_cache_protector = NULL;
/* Create cache ID like a pair of ZIDs. ZID with lowest value at the beginning */
-static void cache_create_id( const zrtp_stringn_t* first_ZID,
+void zrtp_cache_create_id( const zrtp_stringn_t* first_ZID,
const zrtp_stringn_t* second_ZID,
zrtp_cache_id_t id);
zrtp_cache_elem_t* new_elem = NULL;
ZRTP_CACHE_CHECK_ZID(one_ZID, another_ZID);
- cache_create_id(one_ZID, another_ZID, id);
+ zrtp_cache_create_id(one_ZID, another_ZID, id);
zrtp_mutex_lock(def_cache_protector);
new_elem = get_elem(id, 0);
zrtp_cache_elem_t* elem = NULL;
ZRTP_CACHE_CHECK_ZID(one_ZID, another_ZID);
- cache_create_id(one_ZID, another_ZID, id);
+ zrtp_cache_create_id(one_ZID, another_ZID, id);
zrtp_mutex_lock(def_cache_protector);
elem = get_elem(id, 0);
zrtp_cache_id_t id;
ZRTP_CACHE_CHECK_ZID(one_ZID, another_ZID);
- cache_create_id(one_ZID, another_ZID, id);
+ zrtp_cache_create_id(one_ZID, another_ZID, id);
+
+ {
+ char zid1str[24+1], zid2str[24+1];
+ ZRTP_LOG(3,(_ZTU_,"\tcache_put() zid1=%s, zis2=%s MiTM=%s\n",
+ hex2str(one_ZID->buffer, one_ZID->length, zid1str, sizeof(zid1str)),
+ hex2str(another_ZID->buffer, another_ZID->length, zid2str, sizeof(zid2str)),
+ is_mitm?"YES":"NO"));
+ }
zrtp_mutex_lock(def_cache_protector);
do {
} else {
new_elem->_index = g_cache_elems_counter++;
}
+
+ ZRTP_LOG(3,(_ZTU_,"\tcache_put() can't find element in the cache - create a new entry index=%u.\n", new_elem->_index));
+ }
+ else {
+ ZRTP_LOG(3,(_ZTU_,"\tcache_put() Just update existing value.\n"));
}
/* Save current cache value as previous one and new as a current */
zrtp_cache_elem_t* curr = 0;
zrtp_cache_id_t id;
zrtp_status_t s = zrtp_status_ok;
+
+ {
+ char zid1str[24+1], zid2str[24+1];
+ ZRTP_LOG(3,(_ZTU_,"\tache_get(): zid1=%s, zis2=%s MiTM=%s\n",
+ hex2str(one_ZID->buffer, one_ZID->length, zid1str, sizeof(zid1str)),
+ hex2str(another_ZID->buffer, another_ZID->length, zid2str, sizeof(zid2str)),
+ is_mitm?"YES":"NO"));
+ }
ZRTP_CACHE_CHECK_ZID(one_ZID, another_ZID);
- cache_create_id(one_ZID, another_ZID, id);
+ zrtp_cache_create_id(one_ZID, another_ZID, id);
zrtp_mutex_lock(def_cache_protector);
do {
curr = get_elem(id, is_mitm);
if (!curr || (!curr->prev_cache.length && prev_requested)) {
s = zrtp_status_fail;
+ ZRTP_LOG(3,(_ZTU_,"\tache_get() - not found.\n"));
break;
}
prev_requested ? ZSTR_GV(curr->prev_cache) : ZSTR_GV(curr->curr_cache));
rss->lastused_at = curr->lastused_at;
- if (!is_mitm) {
+ if (!is_mitm) {
rss->ttl = curr->ttl;
}
} while (0);
zrtp_cache_id_t id;
ZRTP_CACHE_CHECK_ZID(one_zid, another_zid);
- cache_create_id(one_zid, another_zid, id);
+ zrtp_cache_create_id(one_zid, another_zid, id);
zrtp_mutex_lock(def_cache_protector);
new_elem = get_elem(id, 0);
if (new_elem) {
- ZRTP_LOG(3,(_ZTU_,"\tTEST! Update counter to %u.\n", counter));
new_elem->presh_counter = counter;
new_elem->_is_dirty = 1;
zrtp_cache_id_t id;
ZRTP_CACHE_CHECK_ZID(one_zid, another_zid);
- cache_create_id(one_zid, another_zid, id);
+ zrtp_cache_create_id(one_zid, another_zid, id);
zrtp_mutex_lock(def_cache_protector);
new_elem = get_elem(id, 0);
if (new_elem) {
- ZRTP_LOG(3,(_ZTU_,"\tTEST! Return counter to %u.\n", new_elem->presh_counter));
*counter = new_elem->presh_counter;
}
zrtp_mutex_unlock(def_cache_protector);
}
/*-----------------------------------------------------------------------------*/
-static void cache_create_id( const zrtp_stringn_t* first_ZID,
+ void zrtp_cache_create_id( const zrtp_stringn_t* first_ZID,
const zrtp_stringn_t* second_ZID,
zrtp_cache_id_t id )
{
unsigned is_unsupported = 0;
ZRTP_LOG(3,(_ZTU_,"\tLoad ZRTP cache from <%s>...\n", zrtp->def_cache_path.buffer));
+
+ g_mitmcache_elems_counter = 0;
+ g_cache_elems_counter = 0;
+ g_needs_rewriting = 0;
/* Try to open existing file. If ther is no cache file - start with empty cache */
#if (ZRTP_PLATFORM == ZP_WIN32)
fclose(cache_file);
return zrtp_status_ok;
}
-
- g_mitmcache_elems_counter = 0;
/*
* Load MitM caches: first 32 bits is a MiTM secrets counter. Read it and then
}
cache_elems_count = zrtp_ntoh32(cache_elems_count);
- g_cache_elems_counter = 0;
-
ZRTP_LOG(3,(_ZTU_,"\tZRTP cache file contains %u RS secrets.\n", cache_elems_count));
for (i=0; i<cache_elems_count; i++)
/*
* Let's calculate cache element position in the file
*/
- printf("flush_elem_(): calculate Element offset for %s..\n", is_mitm?"MiTM":"RS");
+
+// @note: I'm going to remove unused comments when random-access cache get more stable. (vkrykun, Nov 27, 2011)
+// printf("flush_elem_(): calculate Element offset for %s..\n", is_mitm?"MiTM":"RS");
/* Skip the header */
pos += strlen(ZRTP_DEF_CACHE_VERSION_STR)+strlen(ZRTP_DEF_CACHE_VERSION_VAL);
pos += sizeof(uint32_t); /* Skip MiTM secretes count. */
- printf("flush_elem_(): \t pos=%u (Header, MiTM Count).\n", pos);
+// printf("flush_elem_(): \t pos=%u (Header, MiTM Count).\n", pos);
if (is_mitm) {
/* position within MiTM secrets block. */
pos += (elem->_index * ZRTP_MITMCACHE_ELEM_LENGTH);
- printf("flush_elem_(): \t pos=%u (Header, MiTM Count + %u MiTM Secrets).\n", pos, elem->_index);
+// printf("flush_elem_(): \t pos=%u (Header, MiTM Count + %u MiTM Secrets).\n", pos, elem->_index);
} else {
/* Skip MiTM Secrets block */
pos += (g_mitmcache_elems_counter * ZRTP_MITMCACHE_ELEM_LENGTH);
pos += (elem->_index * ZRTP_CACHE_ELEM_LENGTH); /* Skip previous RS elements */
- printf("flush_elem_(): \t pos=%u (Header, MiTM Count + ALL %u Secrets, RS counter and %u prev. RS).\n", pos, g_mitmcache_elems_counter, elem->_index);
+// printf("flush_elem_(): \t pos=%u (Header, MiTM Count + ALL %u Secrets, RS counter and %u prev. RS).\n", pos, g_mitmcache_elems_counter, elem->_index);
}
fseek(cache_file, pos, SEEK_SET);
/* Prepare element for storing, convert all fields to the network byte-order. */
cache_make_cross(elem, &tmp_elem, 0);
- printf("flush_elem_(): write to offset=%lu\n", ftell(cache_file));
+// printf("flush_elem_(): write to offset=%lu\n", ftell(cache_file));
/* Flush the element. */
if (fwrite(&tmp_elem, (is_mitm ? ZRTP_MITMCACHE_ELEM_LENGTH : ZRTP_CACHE_ELEM_LENGTH), 1, cache_file) != 1) {
- printf("flush_elem_(): ERROR!!! write failed!\n");
+// printf("flush_elem_(): ERROR!!! write failed!\n");
return zrtp_status_write_fail;
} else {
elem->_is_dirty = 0;
- printf("flush_elem_(): OK! %lu bytes were written\n", (is_mitm ? ZRTP_MITMCACHE_ELEM_LENGTH : ZRTP_CACHE_ELEM_LENGTH));
+// printf("flush_elem_(): OK! %lu bytes were written\n", (is_mitm ? ZRTP_MITMCACHE_ELEM_LENGTH : ZRTP_CACHE_ELEM_LENGTH));
return zrtp_status_ok;
}
}
/* Open/create file for writing */
#if (ZRTP_PLATFORM == ZP_WIN32)
- if (0 != fopen_s(&cache_file, zrtp->def_cache_path.buffer, "wb+")) {
- ZRTP_LOG(2,(_ZTU_,"\tERROR! unable to open ZRTP cache file <%s>.\n", zrtp->def_cache_path.buffer));
- return zrtp_status_open_fail;
+ if (g_needs_rewriting || 0 != fopen_s(&cache_file, zrtp->def_cache_path.buffer, "r+")) {
+ if (0 != fopen_s(&cache_file, zrtp->def_cache_path.buffer, "w+")) {
+ ZRTP_LOG(2,(_ZTU_,"\tERROR! unable to open ZRTP cache file <%s>.\n", zrtp->def_cache_path.buffer));
+ return zrtp_status_open_fail;
+ }
}
-#else
- cache_file = fopen(zrtp->def_cache_path.buffer, "wb+");
- if (!cache_file) {
- ZRTP_LOG(2,(_ZTU_,"\tERROR! unable to open ZRTP cache file <%s>.\n", zrtp->def_cache_path.buffer));
- return zrtp_status_open_fail;
+#else
+ if (g_needs_rewriting || !(cache_file = fopen(zrtp->def_cache_path.buffer, "r+"))) {
+ cache_file = fopen(zrtp->def_cache_path.buffer, "w+");
+ if (!cache_file) {
+ ZRTP_LOG(2,(_ZTU_,"\tERROR! unable to open ZRTP cache file <%s>.\n", zrtp->def_cache_path.buffer));
+ return zrtp_status_open_fail;
+ }
}
#endif
+
+ fseek(cache_file, 0, SEEK_SET);
/* Store version string first. Format: &ZRTP_DEF_CACHE_VERSION_STR&ZRTP_DEF_CACHE_VERSION_VAL */
if (1 != fwrite(ZRTP_DEF_CACHE_VERSION_STR, strlen(ZRTP_DEF_CACHE_VERSION_STR), 1, cache_file)) {
mlist_for_each(node, &mitmcache_head) {
zrtp_cache_elem_t* elem = mlist_get_struct(zrtp_cache_elem_t, _mlist, node);
/* Store dirty values only. */
- if (elem->_is_dirty) {
- printf("zrtp_cache_user_down: Store MiTM elem index=%u, not modified.\n", elem->_index);
+ if (g_needs_rewriting || elem->_is_dirty) {
+// printf("zrtp_cache_user_down: Store MiTM elem index=%u, not modified.\n", elem->_index);
if (zrtp_status_ok != flush_elem_(elem, cache_file, 1)) {
ZRTP_DOWN_CACHE_RETURN(zrtp_status_write_fail, cache_file);
}
} else {
- printf("zrtp_cache_user_down: Skip MiTM elem index=%u, not modified.\n", elem->_index);
+// printf("zrtp_cache_user_down: Skip MiTM elem index=%u, not modified.\n", elem->_index);
}
}
zrtp_cache_elem_t* elem = mlist_get_struct(zrtp_cache_elem_t, _mlist, node);
/* Store dirty values only. */
- if (elem->_is_dirty) {
- printf("zrtp_cache_user_down: Store RS elem index=%u, not modified.\n", elem->_index);
+ if (g_needs_rewriting || elem->_is_dirty) {
+// printf("zrtp_cache_user_down: Store RS elem index=%u, not modified.\n", elem->_index);
if (zrtp_status_ok != flush_elem_(elem, cache_file, 0)) {
ZRTP_DOWN_CACHE_RETURN(zrtp_status_write_fail, cache_file);
}
- } else {
- printf("zrtp_cache_user_down: Skip RS elem index=%u, not modified.\n", elem->_index);
}
+// else {
+// printf("zrtp_cache_user_down: Skip RS elem index=%u, not modified.\n", elem->_index);
+// }
}
fseek(cache_file, pos, SEEK_SET);
ZRTP_DOWN_CACHE_RETURN(zrtp_status_write_fail, cache_file);
}
ZRTP_LOG(3,(_ZTU_,"\t%u regular cache entries have been stored successfully.\n", zrtp_ntoh32(count)));
+
+ g_needs_rewriting = 0;
ZRTP_DOWN_CACHE_RETURN(zrtp_status_ok, cache_file);
}
zrtp_status_t s = zrtp_status_ok;
ZRTP_CACHE_CHECK_ZID(one_ZID, another_ZID);
- cache_create_id(one_ZID, another_ZID, id);
+ zrtp_cache_create_id(one_ZID, another_ZID, id);
zrtp_mutex_lock(def_cache_protector);
do {
zrtp_status_t s = zrtp_status_fail;
ZRTP_CACHE_CHECK_ZID(one_ZID, another_ZID);
- cache_create_id(one_ZID, another_ZID, id);
+ zrtp_cache_create_id(one_ZID, another_ZID, id);
zrtp_mutex_lock(def_cache_protector);
do {
zrtp_cache_id_t id;
ZRTP_CACHE_CHECK_ZID(one_ZID, another_ZID);
- cache_create_id(one_ZID, another_ZID, id);
+ zrtp_cache_create_id(one_ZID, another_ZID, id);
zrtp_mutex_lock(def_cache_protector);
new_elem = get_elem(id, 0);
zrtp_cache_id_t id;
ZRTP_CACHE_CHECK_ZID(one_zid, another_zid);
- cache_create_id(one_zid, another_zid, id);
+ zrtp_cache_create_id(one_zid, another_zid, id);
zrtp_mutex_lock(def_cache_protector);
new_elem = get_elem(id, 0);
void *data)
{
int delete, result;
+ unsigned index_decrease = 0;
mlist_t* node = NULL, *tmp_node = NULL;
- zrtp_mutex_lock(def_cache_protector);
+ zrtp_mutex_lock(def_cache_protector);
mlist_for_each_safe(node, tmp_node, (is_mitm ? &mitmcache_head : &cache_head))
- {
+ {
zrtp_cache_elem_t* elem = mlist_get_struct(zrtp_cache_elem_t, _mlist, node);
+
+ /*
+ * We are about to delete cache element, in order to keep our
+ * random-access file working, we should re-arrange indexes of
+ * cache elements go after the deleting one.
+ */
+ if (index_decrease >0) {
+ elem->_index -= index_decrease;
+ }
+
+ delete = 0;
result = callback(elem, is_mitm, data, &delete);
if (delete) {
+ {
+ char idstr[24*2+1];
+ ZRTP_LOG(3,(_ZTU_,"\zrtp_def_cache_foreach() Delete element id=%s index=%u\n",
+ hex2str(elem->id, sizeof(elem->id), idstr, sizeof(idstr)),
+ elem->_index));
+ }
+
+ index_decrease++;
+
mlist_del(&elem->_mlist);
+ /* Decrement global cache counter. */
if (is_mitm)
g_mitmcache_elems_counter--;
else
g_cache_elems_counter--;
-
- // TODO: rearrange INDEXES here!
+ g_needs_rewriting = 1;
}
if (!result) {
break;
+/*
+ * libZRTP SDK library, implements the ZRTP secure VoIP protocol.
+ * Copyright (c) 2006-2009 Philip R. Zimmermann. All rights reserved.
+ * Contact: http://philzimmermann.com
+ * For licensing and other legal details, see the file zrtp_legal.c.
+ *
+ * Viktor Krykun <v.krikun at zfoneproject.com>
+ */
+
#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
static zrtp_global_t g_zrtp_cfg;
+static zrtp_string16_t zid_my = ZSTR_INIT_WITH_CONST_CSTRING("000000000_00");
+static zrtp_string16_t zid_a = ZSTR_INIT_WITH_CONST_CSTRING("000000000_02");
+static zrtp_string16_t zid_b = ZSTR_INIT_WITH_CONST_CSTRING("000000000_03");
+static zrtp_string16_t zid_c = ZSTR_INIT_WITH_CONST_CSTRING("000000000_04");
+static zrtp_string16_t zid_mitm1 = ZSTR_INIT_WITH_CONST_CSTRING("000000000_m1");
+static zrtp_string16_t zid_mitm2 = ZSTR_INIT_WITH_CONST_CSTRING("000000000_m2");
+
+static zrtp_shared_secret_t rs_my4a, rs_my4b, rs_my4c, rs_my4mitm1, rs_my4mitm2;
+static zrtp_shared_secret_t rs_my4a_r, rs_my4b_r, rs_my4c_r, rs_my4mitm1_r, rs_my4mitm2_r;
+
+static zrtp_cache_id_t secerets_to_delete[24];
+static unsigned secerets_to_delete_count = 0;
+
+static void init_rs_secret_(zrtp_shared_secret_t *sec, unsigned char val_fill);
+
+extern void zrtp_cache_create_id(const zrtp_stringn_t* first_ZID,
+ const zrtp_stringn_t* second_ZID,
+ zrtp_cache_id_t id);
+
+
void cache_setup() {
+ zrtp_status_t status;
+
+ /* Delete cache file from previous test if it exists. */
remove(TEST_CACHE_PATH);
+ secerets_to_delete_count = 0;
+
ZSTR_SET_EMPTY(g_zrtp_cfg.def_cache_path);
/* Configure and Initialize ZRTP cache */
zrtp_zstrcpyc(ZSTR_GV(g_zrtp_cfg.def_cache_path), TEST_CACHE_PATH);
-}
+
+ init_rs_secret_(&rs_my4a, 'a'); init_rs_secret_(&rs_my4b, 'b'); init_rs_secret_(&rs_my4c, 'c');
+ init_rs_secret_(&rs_my4mitm1, '1'); init_rs_secret_(&rs_my4mitm2, '2');
-void cache_teardown() {
+ init_rs_secret_(&rs_my4a_r, 0); init_rs_secret_(&rs_my4b_r, 0); init_rs_secret_(&rs_my4c_r, 0);
+ init_rs_secret_(&rs_my4mitm1_r, 0); init_rs_secret_(&rs_my4mitm2_r, 0);
+
+ /* It should NOT crash and return OK. */
+ status = zrtp_def_cache_init(&g_zrtp_cfg);
+ assert_int_equal(status, zrtp_status_ok);
+
+ /* Add few values into it */
+ printf("==> Add few test entries.\n");
+
+ status = zrtp_def_cache_put(ZSTR_GV(zid_my), ZSTR_GV(zid_a), &rs_my4a);
+ assert_int_equal(status, zrtp_status_ok);
+ status = zrtp_def_cache_put(ZSTR_GV(zid_my), ZSTR_GV(zid_b), &rs_my4b);
+ assert_int_equal(status, zrtp_status_ok);
+ status = zrtp_def_cache_put(ZSTR_GV(zid_my), ZSTR_GV(zid_c), &rs_my4c);
+ assert_int_equal(status, zrtp_status_ok);
+
+ status = zrtp_def_cache_put_mitm(ZSTR_GV(zid_my), ZSTR_GV(zid_mitm1), &rs_my4mitm1);
+ assert_int_equal(status, zrtp_status_ok);
+ status = zrtp_def_cache_put_mitm(ZSTR_GV(zid_my), ZSTR_GV(zid_mitm2), &rs_my4mitm2);
+ assert_int_equal(status, zrtp_status_ok);
+
+ status = zrtp_def_cache_put(ZSTR_GV(zid_my), ZSTR_GV(zid_c), &rs_my4c);
+ assert_int_equal(status, zrtp_status_ok);
+
+ /* Close the cache, it should be flushed to the file. */
+ printf("==> Close the cache.\n");
+
zrtp_def_cache_down();
-}
-
-static void init_rs_secret_(zrtp_shared_secret_t *sec) {
- ZSTR_SET_EMPTY(sec->value);
- sec->_cachedflag = 0;
- sec->ttl = 0;
- sec->lastused_at = 0;
+ printf("==> Open just prepared cache file.\n");
+
+ status = zrtp_def_cache_init(&g_zrtp_cfg);
+ assert_int_equal(status, zrtp_status_ok);
+
+ printf("==> Ready for the test!.\n");
}
+void cache_teardown() {
+ zrtp_def_cache_down();
+}
/*
* Simply init ZRTP cache with empty or non-existing filer and close it.
* The app should not crash and trigger no errors.
*/
void cache_init_store_empty_test() {
- zrtp_status_t status;
-
- /* It should NOT crash and return OK. */
- status = zrtp_def_cache_init(&g_zrtp_cfg);
- assert_int_equal(status, zrtp_status_ok);
-
zrtp_def_cache_down();
}
* all the entries were restored successfully.
*/
void cache_add2empty_test() {
- zrtp_status_t status;
-
+ zrtp_status_t status;
int intres;
- zrtp_string16_t zid_my = ZSTR_INIT_WITH_CONST_CSTRING("000000000_01");
- zrtp_string16_t zid_a = ZSTR_INIT_WITH_CONST_CSTRING("000000000_02");
- zrtp_string16_t zid_b = ZSTR_INIT_WITH_CONST_CSTRING("000000000_03");
- zrtp_string16_t zid_c = ZSTR_INIT_WITH_CONST_CSTRING("000000000_04");
- zrtp_string16_t zid_mitm1 = ZSTR_INIT_WITH_CONST_CSTRING("000000000_04");
+ /* Now, let's open the cache again and check if all the previously added values were restored successfully */
+ printf("==> And open it again, it should contain all the stored values.\n");
+
+ status = zrtp_def_cache_get(ZSTR_GV(zid_my), ZSTR_GV(zid_a), &rs_my4a_r, 0);
+ assert_int_equal(status, zrtp_status_ok);
+ assert_false(zrtp_zstrcmp(ZSTR_GV(rs_my4a_r.value), ZSTR_GV(rs_my4a.value)));
- zrtp_shared_secret_t rs_my4a, rs_my4b, rs_my4c, rs_my4mitm1;
- zrtp_shared_secret_t rs_my4a_r, rs_my4b_r, rs_my4c_r, rs_my4mitm1_r;
+ status = zrtp_def_cache_get(ZSTR_GV(zid_my), ZSTR_GV(zid_b), &rs_my4b_r, 0);
+ assert_int_equal(status, zrtp_status_ok);
+ assert_false(zrtp_zstrcmp(ZSTR_GV(rs_my4b_r.value), ZSTR_GV(rs_my4b.value)));
+
+ status = zrtp_def_cache_get_mitm(ZSTR_GV(zid_my), ZSTR_GV(zid_mitm1), &rs_my4mitm1_r);
+ assert_int_equal(status, zrtp_status_ok);
+ assert_false(zrtp_zstrcmp(ZSTR_GV(rs_my4mitm1_r.value), ZSTR_GV(rs_my4mitm1.value)));
- init_rs_secret_(&rs_my4a); init_rs_secret_(&rs_my4b);
- init_rs_secret_(&rs_my4c); init_rs_secret_(&rs_my4mitm1);
+ status = zrtp_def_cache_get_mitm(ZSTR_GV(zid_my), ZSTR_GV(zid_mitm2), &rs_my4mitm2_r);
+ assert_int_equal(status, zrtp_status_ok);
+ assert_false(zrtp_zstrcmp(ZSTR_GV(rs_my4mitm2_r.value), ZSTR_GV(rs_my4mitm2.value)));
+}
- init_rs_secret_(&rs_my4a_r); init_rs_secret_(&rs_my4b_r);
- init_rs_secret_(&rs_my4c_r); init_rs_secret_(&rs_my4mitm1_r);
+/*
+ * Test if cache properly handles Open-Close-Open with now no changes to the cache values.
+ */
+void cache_save_unchanged_test() {
+ zrtp_status_t status;
+
+ /* Now, let's open the cache again and check if all the previously added values were restored successfully */
+ printf("==> Now let's Open the cache and Close it right after, make no changes.\n");
- printf("Open empty cache file for.\n");
+ zrtp_def_cache_down();
+
+ /*
+ * TEST: now let's store the cache making no changes to it.
+ * After opening it should include all the secrets untouched.
+ */
+
+ printf("==> And the cache again, it should contain all the stored values.\n");
+
status = zrtp_def_cache_init(&g_zrtp_cfg);
assert_int_equal(status, zrtp_status_ok);
- /* Test if cache-init does bot corrupt config. */
- assert_false(strncmp(g_zrtp_cfg.def_cache_path.buffer, TEST_CACHE_PATH, strlen(TEST_CACHE_PATH)));
-
- /* Add few values into it */
- printf("Add few test entries.\n");
+ status = zrtp_def_cache_get(ZSTR_GV(zid_my), ZSTR_GV(zid_a), &rs_my4a_r, 0);
+ assert_int_equal(status, zrtp_status_ok);
+ assert_false(zrtp_zstrcmp(ZSTR_GV(rs_my4a_r.value), ZSTR_GV(rs_my4a.value)));
- status = zrtp_def_cache_put(ZSTR_GV(zid_my), ZSTR_GV(zid_a), &rs_my4a);
+ status = zrtp_def_cache_get(ZSTR_GV(zid_my), ZSTR_GV(zid_b), &rs_my4b_r, 0);
+ assert_int_equal(status, zrtp_status_ok);
+ assert_false(zrtp_zstrcmp(ZSTR_GV(rs_my4b_r.value), ZSTR_GV(rs_my4b.value)));
+
+ status = zrtp_def_cache_get_mitm(ZSTR_GV(zid_my), ZSTR_GV(zid_mitm1), &rs_my4mitm1_r);
assert_int_equal(status, zrtp_status_ok);
+ assert_false(zrtp_zstrcmp(ZSTR_GV(rs_my4mitm1_r.value), ZSTR_GV(rs_my4mitm1.value)));
- status = zrtp_def_cache_put(ZSTR_GV(zid_my), ZSTR_GV(zid_b), &rs_my4b);
+ status = zrtp_def_cache_get_mitm(ZSTR_GV(zid_my), ZSTR_GV(zid_mitm2), &rs_my4mitm2_r);
assert_int_equal(status, zrtp_status_ok);
+ assert_false(zrtp_zstrcmp(ZSTR_GV(rs_my4mitm2_r.value), ZSTR_GV(rs_my4mitm2.value)));
+}
+
+/*
+ * Check how the cache handles flushing of several dirty (modified) values. The cache should
+ * flush to the disk modified values only and leave rest of the items untouched.
+ */
+void cache_modify_and_save_test() {
+ zrtp_status_t status;
+ int intres;
+
+ printf("==> And open it again, it should contain all the stored values.\n");
+
+ /*
+ * Now, let's modify just few entries and check of the fill will be stored.
+ *
+ * We will change RS secrets rs_my4b, rs_my4c and rs_my4mitm1 while leaving
+ * rs_my4a and rs_my4mitm2 untouched.
+ */
+
+ init_rs_secret_(&rs_my4b, 'x'); init_rs_secret_(&rs_my4c, 'y');
+ init_rs_secret_(&rs_my4mitm1, 'z');
+
+ printf("==> Now we gonna to update few cache entries and flush the cache mack to the file.\n");
+ status = zrtp_def_cache_put(ZSTR_GV(zid_my), ZSTR_GV(zid_b), &rs_my4b);
+ assert_int_equal(status, zrtp_status_ok);
+ status = zrtp_def_cache_put(ZSTR_GV(zid_my), ZSTR_GV(zid_c), &rs_my4c);
+ assert_int_equal(status, zrtp_status_ok);
status = zrtp_def_cache_put_mitm(ZSTR_GV(zid_my), ZSTR_GV(zid_mitm1), &rs_my4mitm1);
assert_int_equal(status, zrtp_status_ok);
+
+ /* Flush the cache and open it again. */
+ zrtp_def_cache_down();
- status = zrtp_def_cache_put(ZSTR_GV(zid_my), ZSTR_GV(zid_c), &rs_my4c);
+ printf("==> Open the cache and make sure all our prev. modifications saved properly.\n");
+
+ status = zrtp_def_cache_init(&g_zrtp_cfg);
assert_int_equal(status, zrtp_status_ok);
- /* Close the cache, it should be flushed to the file. */
- printf("Close the cache.\n");
+ /* Let's check if all our modifications are in place. */
+ status = zrtp_def_cache_get(ZSTR_GV(zid_my), ZSTR_GV(zid_a), &rs_my4a_r, 0);
+ assert_int_equal(status, zrtp_status_ok);
+ assert_false(zrtp_zstrcmp(ZSTR_GV(rs_my4a_r.value), ZSTR_GV(rs_my4a.value)));
+
+ status = zrtp_def_cache_get(ZSTR_GV(zid_my), ZSTR_GV(zid_b), &rs_my4b_r, 0);
+ assert_int_equal(status, zrtp_status_ok);
+ assert_false(zrtp_zstrcmp(ZSTR_GV(rs_my4b_r.value), ZSTR_GV(rs_my4b.value)));
+
+ status = zrtp_def_cache_get(ZSTR_GV(zid_my), ZSTR_GV(zid_c), &rs_my4c_r, 0);
+ assert_int_equal(status, zrtp_status_ok);
+ assert_false(zrtp_zstrcmp(ZSTR_GV(rs_my4c_r.value), ZSTR_GV(rs_my4c.value)));
+
+ status = zrtp_def_cache_get_mitm(ZSTR_GV(zid_my), ZSTR_GV(zid_mitm1), &rs_my4mitm1_r);
+ assert_int_equal(status, zrtp_status_ok);
+ assert_false(zrtp_zstrcmp(ZSTR_GV(rs_my4mitm1_r.value), ZSTR_GV(rs_my4mitm1.value)));
+
+ status = zrtp_def_cache_get_mitm(ZSTR_GV(zid_my), ZSTR_GV(zid_mitm2), &rs_my4mitm2_r);
+ assert_int_equal(status, zrtp_status_ok);
+ assert_false(zrtp_zstrcmp(ZSTR_GV(rs_my4mitm2_r.value), ZSTR_GV(rs_my4mitm2.value)));
+}
+
+/*
+ * The basic idea of all cache_delete_* tests is to delete few cache entries
+ * from preconfigured setup, flush caches, open the cache again and check if
+ * non-deleted values are Ok.
+ */
+
+static int cache_foreach_del_func(zrtp_cache_elem_t* elem, int is_mitm, void* data, int* del) {
+ unsigned c;
+
+ //printf("AAAA cache_foreach_del_func(): elem index=%u\n", elem->_index);
+
+ for (c=0; c<secerets_to_delete_count; c++) {
+ if (!zrtp_memcmp(elem->id, secerets_to_delete[c], sizeof(zrtp_cache_id_t))) {
+ printf("\t==> Delete cache element index=%u.\n", elem->_index);
+ *del = 1;
+ break;
+ }
+ }
+
+ return 1;
+}
+
+void cache_delete_few_rs_test() {
+ zrtp_status_t status;
+ printf("==> Delete few RS secrets and flush the cache.\n");
+
+ secerets_to_delete_count = 0;
+ zrtp_cache_create_id(ZSTR_GV(zid_my), ZSTR_GV(zid_b), secerets_to_delete[secerets_to_delete_count++]);
+ zrtp_cache_create_id(ZSTR_GV(zid_my), ZSTR_GV(zid_a), secerets_to_delete[secerets_to_delete_count++]);
+
+ zrtp_def_cache_foreach(&g_zrtp_cfg, 0, &cache_foreach_del_func, NULL);
+
+ /* Flush the cache and open it again. */
zrtp_def_cache_down();
-
- /* Test if cache-close does bot corrupt config. */
- assert_false(strncmp(g_zrtp_cfg.def_cache_path.buffer, TEST_CACHE_PATH, strlen(TEST_CACHE_PATH)));
- /* Now, let's open the cache again and check if all the previously added values were restored successfully */
- printf("And open it again, it should contain all the stored values.\n");
+ printf("==> Open the cache and make sure all our prev. Modifications saved properly.\n");
status = zrtp_def_cache_init(&g_zrtp_cfg);
assert_int_equal(status, zrtp_status_ok);
+ /* Let's check if all our modifications are in place. */
+
+ /* my4a should be deleted. */
+ status = zrtp_def_cache_get(ZSTR_GV(zid_my), ZSTR_GV(zid_a), &rs_my4a_r, 0);
+ assert_int_not_equal(status, zrtp_status_ok);
+
+ /* my4b should be deleted. */
+ status = zrtp_def_cache_get(ZSTR_GV(zid_my), ZSTR_GV(zid_b), &rs_my4b_r, 0);
+ assert_int_not_equal(status, zrtp_status_ok);
+
+ /* The rest of the secrets should be in place. */
+ status = zrtp_def_cache_get(ZSTR_GV(zid_my), ZSTR_GV(zid_c), &rs_my4c_r, 0);
+ assert_int_equal(status, zrtp_status_ok);
+ assert_false(zrtp_zstrcmp(ZSTR_GV(rs_my4c_r.value), ZSTR_GV(rs_my4c.value)));
+
+ status = zrtp_def_cache_get_mitm(ZSTR_GV(zid_my), ZSTR_GV(zid_mitm1), &rs_my4mitm1_r);
+ assert_int_equal(status, zrtp_status_ok);
+ assert_false(zrtp_zstrcmp(ZSTR_GV(rs_my4mitm1_r.value), ZSTR_GV(rs_my4mitm1.value)));
+
+ status = zrtp_def_cache_get_mitm(ZSTR_GV(zid_my), ZSTR_GV(zid_mitm2), &rs_my4mitm2_r);
+ assert_int_equal(status, zrtp_status_ok);
+ assert_false(zrtp_zstrcmp(ZSTR_GV(rs_my4mitm2_r.value), ZSTR_GV(rs_my4mitm2.value)));
+}
+
+void cache_delete_few_mitm_test() {
+ zrtp_status_t status;
+
+ printf("==> Delete few MiTM secrets and flush the cache.\n");
+
+ secerets_to_delete_count = 0;
+ zrtp_cache_create_id(ZSTR_GV(zid_my), ZSTR_GV(zid_mitm1), secerets_to_delete[secerets_to_delete_count++]);
+
+ zrtp_def_cache_foreach(&g_zrtp_cfg, 1, &cache_foreach_del_func, NULL);
+
+ /* Flush the cache and open it again. */
+ zrtp_def_cache_down();
+
+ printf("==> Open the cache and make sure all our prev. Modifications saved properly.\n");
+
+ status = zrtp_def_cache_init(&g_zrtp_cfg);
+ assert_int_equal(status, zrtp_status_ok);
+
+ /* Let's check if all our modifications are in place. */
status = zrtp_def_cache_get(ZSTR_GV(zid_my), ZSTR_GV(zid_a), &rs_my4a_r, 0);
assert_int_equal(status, zrtp_status_ok);
-
assert_false(zrtp_zstrcmp(ZSTR_GV(rs_my4a_r.value), ZSTR_GV(rs_my4a.value)));
- /* Test if cache-close does bot corrupt config. */
- assert_false(strncmp(g_zrtp_cfg.def_cache_path.buffer, TEST_CACHE_PATH, strlen(TEST_CACHE_PATH)));
+ status = zrtp_def_cache_get(ZSTR_GV(zid_my), ZSTR_GV(zid_b), &rs_my4b_r, 0);
+ assert_int_equal(status, zrtp_status_ok);
+ assert_false(zrtp_zstrcmp(ZSTR_GV(rs_my4b_r.value), ZSTR_GV(rs_my4b.value)));
+
+ status = zrtp_def_cache_get(ZSTR_GV(zid_my), ZSTR_GV(zid_c), &rs_my4c_r, 0);
+ assert_int_equal(status, zrtp_status_ok);
+ assert_false(zrtp_zstrcmp(ZSTR_GV(rs_my4c_r.value), ZSTR_GV(rs_my4c.value)));
+
+ /* Should be deleted */
+ status = zrtp_def_cache_get_mitm(ZSTR_GV(zid_my), ZSTR_GV(zid_mitm1), &rs_my4mitm1_r);
+ assert_int_not_equal(status, zrtp_status_ok);
+
+ status = zrtp_def_cache_get_mitm(ZSTR_GV(zid_my), ZSTR_GV(zid_mitm2), &rs_my4mitm2_r);
+ assert_int_equal(status, zrtp_status_ok);
+ assert_false(zrtp_zstrcmp(ZSTR_GV(rs_my4mitm2_r.value), ZSTR_GV(rs_my4mitm2.value)));
+}
+
+void cache_delete_few_rs_and_mitm_test() {
+ zrtp_status_t status;
+
+ printf("==> Delete few RS secrets and flush the cache.\n");
+
+ secerets_to_delete_count = 0;
+ zrtp_cache_create_id(ZSTR_GV(zid_my), ZSTR_GV(zid_b), secerets_to_delete[secerets_to_delete_count++]);
+ zrtp_cache_create_id(ZSTR_GV(zid_my), ZSTR_GV(zid_a), secerets_to_delete[secerets_to_delete_count++]);
+
+ zrtp_def_cache_foreach(&g_zrtp_cfg, 0, &cache_foreach_del_func, NULL);
+
+ secerets_to_delete_count = 0;
+ zrtp_cache_create_id(ZSTR_GV(zid_my), ZSTR_GV(zid_mitm1), secerets_to_delete[secerets_to_delete_count++]);
+
+ zrtp_def_cache_foreach(&g_zrtp_cfg, 1, &cache_foreach_del_func, NULL);
+
+ /* Flush the cache and open it again. */
+ zrtp_def_cache_down();
+
+ printf("==> Open the cache and make sure all our prev. Modifications saved properly.\n");
+
+ status = zrtp_def_cache_init(&g_zrtp_cfg);
+ assert_int_equal(status, zrtp_status_ok);
+
+ /* Let's check if all our modifications are in place. */
+
+ /* Should be deleted. */
+ status = zrtp_def_cache_get(ZSTR_GV(zid_my), ZSTR_GV(zid_a), &rs_my4a_r, 0);
+ assert_int_not_equal(status, zrtp_status_ok);
+
+ /* Should be deleted. */
+ status = zrtp_def_cache_get(ZSTR_GV(zid_my), ZSTR_GV(zid_b), &rs_my4b_r, 0);
+ assert_int_not_equal(status, zrtp_status_ok);
+
+ status = zrtp_def_cache_get(ZSTR_GV(zid_my), ZSTR_GV(zid_c), &rs_my4c_r, 0);
+ assert_int_equal(status, zrtp_status_ok);
+ assert_false(zrtp_zstrcmp(ZSTR_GV(rs_my4c_r.value), ZSTR_GV(rs_my4c.value)));
+
+ /* Should be deleted. */
+ status = zrtp_def_cache_get_mitm(ZSTR_GV(zid_my), ZSTR_GV(zid_mitm1), &rs_my4mitm1_r);
+ assert_int_not_equal(status, zrtp_status_ok);
+
+ status = zrtp_def_cache_get_mitm(ZSTR_GV(zid_my), ZSTR_GV(zid_mitm2), &rs_my4mitm2_r);
+ assert_int_equal(status, zrtp_status_ok);
+ assert_false(zrtp_zstrcmp(ZSTR_GV(rs_my4mitm2_r.value), ZSTR_GV(rs_my4mitm2.value)));
}
+void cache_delete_all_rs_test() {
+ zrtp_status_t status;
+
+ printf("==> Delete few RS secrets and flush the cache.\n");
+
+ secerets_to_delete_count = 0;
+ zrtp_cache_create_id(ZSTR_GV(zid_my), ZSTR_GV(zid_b), secerets_to_delete[secerets_to_delete_count++]);
+ zrtp_cache_create_id(ZSTR_GV(zid_my), ZSTR_GV(zid_a), secerets_to_delete[secerets_to_delete_count++]);
+ zrtp_cache_create_id(ZSTR_GV(zid_my), ZSTR_GV(zid_c), secerets_to_delete[secerets_to_delete_count++]);
+
+ zrtp_def_cache_foreach(&g_zrtp_cfg, 0, &cache_foreach_del_func, NULL);
+
+ /* Flush the cache and open it again. */
+ zrtp_def_cache_down();
+
+ printf("==> Open the cache and make sure all our prev. Modifications saved properly.\n");
+
+ status = zrtp_def_cache_init(&g_zrtp_cfg);
+ assert_int_equal(status, zrtp_status_ok);
+
+ /* Let's check if all our modifications are in place. */
+
+ /* All RS values should be deleted. */
+ status = zrtp_def_cache_get(ZSTR_GV(zid_my), ZSTR_GV(zid_a), &rs_my4a_r, 0);
+ assert_int_not_equal(status, zrtp_status_ok);
+
+ status = zrtp_def_cache_get(ZSTR_GV(zid_my), ZSTR_GV(zid_b), &rs_my4b_r, 0);
+ assert_int_not_equal(status, zrtp_status_ok);
+
+ status = zrtp_def_cache_get(ZSTR_GV(zid_my), ZSTR_GV(zid_c), &rs_my4c_r, 0);
+ assert_int_not_equal(status, zrtp_status_ok);
+
+ /* MiTM secrets should be in place. */
+ status = zrtp_def_cache_get_mitm(ZSTR_GV(zid_my), ZSTR_GV(zid_mitm1), &rs_my4mitm1_r);
+ assert_int_equal(status, zrtp_status_ok);
+ assert_false(zrtp_zstrcmp(ZSTR_GV(rs_my4mitm1_r.value), ZSTR_GV(rs_my4mitm1.value)));
+
+ status = zrtp_def_cache_get_mitm(ZSTR_GV(zid_my), ZSTR_GV(zid_mitm2), &rs_my4mitm2_r);
+ assert_int_equal(status, zrtp_status_ok);
+ assert_false(zrtp_zstrcmp(ZSTR_GV(rs_my4mitm2_r.value), ZSTR_GV(rs_my4mitm2.value)));
+}
+void cache_delete_all_mitm_test() {
+ zrtp_status_t status;
+
+ printf("==> Delete few MiTM secrets and flush the cache.\n");
+
+ secerets_to_delete_count = 0;
+ zrtp_cache_create_id(ZSTR_GV(zid_my), ZSTR_GV(zid_mitm1), secerets_to_delete[secerets_to_delete_count++]);
+ zrtp_cache_create_id(ZSTR_GV(zid_my), ZSTR_GV(zid_mitm2), secerets_to_delete[secerets_to_delete_count++]);
+
+ zrtp_def_cache_foreach(&g_zrtp_cfg, 1, &cache_foreach_del_func, NULL);
+
+ /* Flush the cache and open it again. */
+ zrtp_def_cache_down();
+
+ printf("==> Open the cache and make sure all our prev. Modifications saved properly.\n");
+
+ status = zrtp_def_cache_init(&g_zrtp_cfg);
+ assert_int_equal(status, zrtp_status_ok);
+
+ /* Let's check if all our modifications are in place. */
+ status = zrtp_def_cache_get(ZSTR_GV(zid_my), ZSTR_GV(zid_a), &rs_my4a_r, 0);
+ assert_int_equal(status, zrtp_status_ok);
+ assert_false(zrtp_zstrcmp(ZSTR_GV(rs_my4a_r.value), ZSTR_GV(rs_my4a.value)));
+
+ status = zrtp_def_cache_get(ZSTR_GV(zid_my), ZSTR_GV(zid_b), &rs_my4b_r, 0);
+ assert_int_equal(status, zrtp_status_ok);
+ assert_false(zrtp_zstrcmp(ZSTR_GV(rs_my4b_r.value), ZSTR_GV(rs_my4b.value)));
+
+ status = zrtp_def_cache_get(ZSTR_GV(zid_my), ZSTR_GV(zid_c), &rs_my4c_r, 0);
+ assert_int_equal(status, zrtp_status_ok);
+ assert_false(zrtp_zstrcmp(ZSTR_GV(rs_my4c_r.value), ZSTR_GV(rs_my4c.value)));
+
+ /* All MiTM secrets should be deleted. */
+ status = zrtp_def_cache_get_mitm(ZSTR_GV(zid_my), ZSTR_GV(zid_mitm1), &rs_my4mitm1_r);
+ assert_int_not_equal(status, zrtp_status_ok);
+
+ assert_int_not_equal(zrtp_def_cache_get_mitm(ZSTR_GV(zid_my), ZSTR_GV(zid_mitm2), &rs_my4mitm2_r), zrtp_status_ok);
+}
int main(void) {
const UnitTest tests[] = {
- //unit_test_setup_teardown(cache_init_store_empty_test, cache_setup, cache_teardown),
+ unit_test_setup_teardown(cache_init_store_empty_test, cache_setup, cache_teardown),
unit_test_setup_teardown(cache_add2empty_test, cache_setup, cache_teardown),
+ unit_test_setup_teardown(cache_save_unchanged_test, cache_setup, cache_teardown),
+ unit_test_setup_teardown(cache_modify_and_save_test, cache_setup, cache_teardown),
+
+ unit_test_setup_teardown(cache_delete_few_rs_test, cache_setup, cache_teardown),
+ unit_test_setup_teardown(cache_delete_few_mitm_test, cache_setup, cache_teardown),
+ unit_test_setup_teardown(cache_delete_few_rs_and_mitm_test, cache_setup, cache_teardown),
+ unit_test_setup_teardown(cache_delete_all_mitm_test, cache_setup, cache_teardown),
};
return run_tests(tests);
}
+
+
+/******************************************************************************
+ * Helpers
+ *****************************************************************************/
+
+static void init_rs_secret_(zrtp_shared_secret_t *sec, unsigned char val_fill) {
+
+ char val_buff[ZRTP_HASH_SIZE];
+ zrtp_memset(val_buff, val_fill, sizeof(val_buff));
+
+ ZSTR_SET_EMPTY(sec->value);
+ zrtp_zstrcpyc(ZSTR_GV(sec->value), val_buff);
+
+ sec->_cachedflag = 0;
+ sec->ttl = 0;
+ sec->lastused_at = 0;
+}