diff --git a/lib/cookies/control.c b/lib/cookies/control.c index e3ddb72eab848ac111c266dfb597d9afa2319826..a2adb4a67c4a41e46f150476bfa418a827cea087 100644 --- a/lib/cookies/control.c +++ b/lib/cookies/control.c @@ -46,6 +46,12 @@ struct kr_cookie_secret dflt_cs = { .data = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; +const struct kr_cc_hash_descr kr_cc_hashes[] = { + { kr_cc_compute_fnv64, "FNV-64" }, + { kr_cc_compute_hmac_sha256_64, "HMAC-SHA256-64" }, + { NULL, NULL } +}; + struct kr_cookie_ctx kr_glob_cookie_ctx = { .enabled = false, .current_cs = &dflt_cs @@ -100,6 +106,45 @@ static int opt_rr_add_option(knot_rrset_t *opt_rr, uint8_t *option, return KNOT_EOK; } +cc_compute_func_t *kr_cc_hash_func(const struct kr_cc_hash_descr cc_hashes[], + const char *name) +{ + if (!cc_hashes || !name) { + return NULL; + } + + const struct kr_cc_hash_descr *aux_ptr = cc_hashes; + + while (aux_ptr && aux_ptr->hash_func) { + assert(aux_ptr->name); + if (strcmp(aux_ptr->name, name) == 0) { + return aux_ptr->hash_func; + } + ++aux_ptr; + } + + return NULL; +} + +const char *kr_cc_hash_name(const struct kr_cc_hash_descr cc_hashes[], + cc_compute_func_t *func) +{ + if (!cc_hashes || !func) { + return NULL; + } + + const struct kr_cc_hash_descr *aux_ptr = cc_hashes; + while (aux_ptr && aux_ptr->hash_func) { + assert(aux_ptr->name); + if (aux_ptr->hash_func == func) { + return aux_ptr->name; + } + ++aux_ptr; + } + + return NULL; +} + int kr_address_bytes(const void *sockaddr, const uint8_t **addr, size_t *len) { if (!sockaddr || !addr || !len) { diff --git a/lib/cookies/control.h b/lib/cookies/control.h index d2ddc2bdf768965056523aed4269cdb5d5fd7ad1..520ae6b54ef7c44eec8564ab19c88222c98caa58 100644 --- a/lib/cookies/control.h +++ b/lib/cookies/control.h @@ -43,6 +43,20 @@ extern struct kr_cookie_secret dflt_cs; typedef int (cc_compute_func_t)(uint8_t *, const void *, const void *, const struct kr_cookie_secret *); +/** Holds description of client cookie hashing algorithms. */ +struct kr_cc_hash_descr { + cc_compute_func_t *hash_func; /**< Pointer to has function. */ + const char *name; /**< Hash function name. */ +}; + +/** + * List of available client cookie hash functions. + * + * Last element contains all null entries. + */ +KR_EXPORT +extern const struct kr_cc_hash_descr kr_cc_hashes[]; + /** DNS cookies controlling structure. */ struct kr_cookie_ctx { bool enabled; /**< Enabled/disables DNS cookies functionality. */ @@ -52,14 +66,33 @@ struct kr_cookie_ctx { uint32_t cache_ttl; /**< TTL used when caching cookies */ - /**< Client cookie computation callback. */ - cc_compute_func_t *cc_compute_func; + cc_compute_func_t *cc_compute_func; /**< Client cookie hash computation callback. */ }; /** Global cookie control context. */ KR_EXPORT extern struct kr_cookie_ctx kr_glob_cookie_ctx; +/** + * @brief Return pointer to client cookie hash function with given name. + * @param cc_hashes list of avilable has functions + * @param name has function name + * @return pointer to function or NULL if not found + */ +KR_EXPORT +cc_compute_func_t *kr_cc_hash_func(const struct kr_cc_hash_descr cc_hashes[], + const char *name); + +/** + * @brief Return name of given client cookie hash function. + * @param cc_hashes list of avilable has functions + * @param func sought function + * @return pointer to string or NULL if not found + */ +KR_EXPORT +const char *kr_cc_hash_name(const struct kr_cc_hash_descr cc_hashes[], + cc_compute_func_t *func); + /** * Get pointers to IP address bytes. * @param sockaddr socket address diff --git a/lib/layer/cookiemonster.c b/lib/layer/cookiemonster.c index 77e5a4c47180793e7dbb83749a452b62ef31b58d..5fe42de9629c5cfa8e8f295412e9df4dad9f50de 100644 --- a/lib/layer/cookiemonster.c +++ b/lib/layer/cookiemonster.c @@ -348,7 +348,7 @@ static int check_response(knot_layer_t *ctx, knot_pkt_t *pkt) KNOT_EDNS_OPTION_COOKIE); } - struct kr_cache *cookie_cache = &req->ctx->cache; //&kr_glob_cookie_ctx.cache; + struct kr_cache *cookie_cache = &req->ctx->cache; const struct sockaddr *srvr_sockaddr = passed_server_sockaddr(qry); diff --git a/modules/cookiectl/cookiectl.c b/modules/cookiectl/cookiectl.c index 93892e9571c9b343c418eb72e85dcd9beecd6610..d62273b2ac884378dbd421c47028ff5d0488a724 100644 --- a/modules/cookiectl/cookiectl.c +++ b/modules/cookiectl/cookiectl.c @@ -45,6 +45,8 @@ static struct storage_api *find_storage_api(const storage_registry_t *registry, #define NAME_ENABLED "enabled" #define NAME_CLIENT_SECRET "client_secret" +#define NAME_CLIENT_HASH_FUNC "client_hash_func" +#define NAME_AVAILABLE_CLIENT_HASH_FUNCS "available_client_hash_funcs" #define NAME_CACHE_TTL "cache_ttl" static bool aply_enabled(struct kr_cookie_ctx *cntrl, const JsonNode *node) @@ -105,7 +107,8 @@ static struct kr_cookie_secret *new_sq_array(const JsonNode *node) return sq; } -static bool apply_client_secret(struct kr_cookie_ctx *cntrl, const JsonNode *node) +static bool apply_client_secret(struct kr_cookie_ctx *cntrl, + const JsonNode *node) { struct kr_cookie_secret *sq = NULL; @@ -142,6 +145,22 @@ static bool apply_client_secret(struct kr_cookie_ctx *cntrl, const JsonNode *nod return true; } +static bool apply_client_hash_func(struct kr_cookie_ctx *cntrl, + const JsonNode *node) +{ + if (node->tag == JSON_STRING) { + cc_compute_func_t *cc_compute_func = kr_cc_hash_func(kr_cc_hashes, + node->string_); + if (!cc_compute_func) { + return false; + } + cntrl->cc_compute_func = cc_compute_func; + return true; + } + + return false; +} + static bool apply_cache_ttl(struct kr_cookie_ctx *cntrl, const JsonNode *node) { if (node->tag == JSON_NUMBER) { @@ -165,6 +184,8 @@ static bool apply_configuration(struct kr_cookie_ctx *cntrl, const JsonNode *nod return aply_enabled(cntrl, node); } else if (strcmp(node->key, NAME_CLIENT_SECRET) == 0) { return apply_client_secret(cntrl, node); + } else if (strcmp(node->key, NAME_CLIENT_HASH_FUNC) == 0) { + return apply_client_hash_func(cntrl, node); } else if (strcmp(node->key, NAME_CACHE_TTL) == 0) { return apply_cache_ttl(cntrl, node); } @@ -200,6 +221,38 @@ fail: return false; } +static bool read_available_cc_hashes(JsonNode *root, + struct kr_cookie_ctx *cntrl) +{ + assert(root && cntrl); + + JsonNode *array = json_mkarray(); + if (!array) { + return false; + } + + const struct kr_cc_hash_descr *aux_ptr = kr_cc_hashes; + while (aux_ptr && aux_ptr->hash_func) { + assert(aux_ptr->name); + JsonNode *element = json_mkstring(aux_ptr->name); + if (!element) { + goto fail; + } + json_append_element(array, element); + ++aux_ptr; + } + + json_append_member(root, NAME_AVAILABLE_CLIENT_HASH_FUNCS, array); + + return true; + +fail: + if (array) { + json_delete(array); + } + return false; +} + /** * Get/set DNS cookie related stuff. * @@ -220,11 +273,23 @@ static char *cookiectl_config(void *env, struct kr_module *module, const char *a /* Return current configuration. */ char *result = NULL; JsonNode *root_node = json_mkobject(); + json_append_member(root_node, NAME_ENABLED, json_mkbool(kr_glob_cookie_ctx.enabled)); + read_secret(root_node, &kr_glob_cookie_ctx); + + const char *name = kr_cc_hash_name(kr_cc_hashes, + kr_glob_cookie_ctx.cc_compute_func); + assert(name); + json_append_member(root_node, NAME_CLIENT_HASH_FUNC, + json_mkstring(name)); + + read_available_cc_hashes(root_node, &kr_glob_cookie_ctx); + json_append_member(root_node, NAME_CACHE_TTL, json_mknumber(kr_glob_cookie_ctx.cache_ttl)); + result = json_encode(root_node); json_delete(root_node); return result; @@ -272,11 +337,8 @@ int cookiectl_init(struct kr_module *module) kr_glob_cookie_ctx.enabled = false; kr_glob_cookie_ctx.current_cs = &dflt_cs; kr_glob_cookie_ctx.cache_ttl = DFLT_COOKIE_TTL; - kr_glob_cookie_ctx.cc_compute_func = kr_cc_compute_fnv64; -// cookies_cache_init(&kr_glob_cookie_ctx.cache, engine); - module->data = NULL; return kr_ok(); @@ -299,8 +361,6 @@ int cookiectl_deinit(struct kr_module *module) } kr_glob_cookie_ctx.current_cs = &dflt_cs; -// kr_cache_close(&kr_glob_cookie_ctx.cache); - return kr_ok(); }