/* * 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 */ #include #include #include #include #include #include "zrtp.h" #include "cmockery/cmockery.h" #define TEST_CACHE_PATH "./zrtp_cache_test.dat" 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'); 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(); 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_def_cache_down(); } /* * Add few entries to the empty cache, flush it and then load again. Check if * all the entries were restored successfully. */ void cache_add2empty_test() { zrtp_status_t status; int intres; /* 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))); 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_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))); } /* * 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"); 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); 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_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))); } /* * 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(); 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))); 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; cid, 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(); 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))); 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_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; }