Commit b4a88628 authored by Karel Slaný's avatar Karel Slaný Committed by Ondřej Surý

Checking cookies in inbound requests.

parent 639a486f
......@@ -349,6 +349,13 @@ static int qr_task_start(struct qr_task *task, knot_pkt_t *query)
task->req.qsource.key = knot_rrset_copy(query->tsig_rr, &task->req.pool);
}
#if defined(ENABLE_COOKIES)
/* Remember query source EDNS data */
if (query->opt_rr) {
task->req.qsource.opt = knot_rrset_copy(query->opt_rr, &task->req.pool);
}
#endif /* defined(ENABLE_COOKIES) */
/* Start resolution */
struct worker_ctx *worker = task->worker;
struct engine *engine = worker->engine;
......
......@@ -160,7 +160,7 @@ static int kr_clnt_cookie_alg_hmac_sha256_64(const struct kr_clnt_cookie_input *
}
const struct kr_clnt_cookie_alg_descr kr_clnt_cookie_algs[] = {
{ "FNV-64", kr_clnt_cookie_alg_fnv64 },
{ "FNV-64", kr_clnt_cookie_alg_fnv64 },
{ "HMAC-SHA256-64", kr_clnt_cookie_alg_hmac_sha256_64 },
{ NULL, NULL }
};
......
This diff is collapsed.
......@@ -29,7 +29,6 @@ struct kr_srvr_cookie_check_ctx {
/** Inbound server cookie content structure. */
struct kr_srvr_cookie_inbound {
const uint8_t *clnt_cookie; /**< Client cookie, `KNOT_OPT_COOKIE_CLNT` bytes long. */
uint32_t nonce; /**< Some value. */
uint32_t time; /**< Time stamp. */
const uint8_t *hash_data; /**< Hash data. */
......@@ -41,17 +40,17 @@ struct kr_srvr_cookie_input {
const uint8_t *clnt_cookie; /**< Client cookie, must be `KNOT_OPT_COOKIE_CLNT` bytes long. */
uint32_t nonce; /**< Some generated value. */
uint32_t time; /**< Cookie time stamp. */
struct kr_srvr_cookie_check_ctx srvr_data; /**< Data known to the server. */
const struct kr_srvr_cookie_check_ctx *srvr_data; /**< Data known to the server. */
};
/**
* @brief Server cookie parser function type.
* @param cookie_data Entire cookie option data (without option header).
* @param data_len Cookie data length.
* @param inbound Inbound cookie structure to be set.
* @param sc Server cookie data.
* @param data_len Server cookie data length.
* @param inbound Inbound cookie structure to be set.
* @return kr_ok() or error code.
*/
typedef int (srvr_cookie_parse_t)(const uint8_t *cookie_data, uint16_t data_len,
typedef int (srvr_cookie_parse_t)(const uint8_t *sc, uint16_t sc_len,
struct kr_srvr_cookie_inbound *inbound);
/**
* @brief Server cookie generator function type.
......@@ -65,10 +64,10 @@ typedef int (srvr_cookie_gen_t)(const struct kr_srvr_cookie_input *input,
/** Holds description of server cookie hashing algorithms. */
struct kr_srvr_cookie_alg_descr {
const char *name; /** Server cookie algorithm name. */
const char *name; /**< Server cookie algorithm name. */
const uint16_t srvr_cookie_size; /**< Size of the generated server cookie. */
const srvr_cookie_parse_t *opt_parse_func; /**< Cookie option parser function. */
const srvr_cookie_gen_t *gen_func; /*< Cookie generator function. */
srvr_cookie_parse_t *opt_parse_func; /**< Cookie option parser function. */
srvr_cookie_gen_t *gen_func; /**< Cookie generator function. */
};
/**
......@@ -79,14 +78,27 @@ struct kr_srvr_cookie_alg_descr {
KR_EXPORT
extern const struct kr_srvr_cookie_alg_descr kr_srvr_cookie_algs[];
/**
* @brief Return pointer to server cookie algorithm with given name.
* @param sc_algs List of available algorithms.
* @param name Algorithm name.
* @return pointer to algorithm or NULL if not found.
*/
KR_EXPORT
const struct kr_srvr_cookie_alg_descr *kr_srvr_cookie_alg(const struct kr_srvr_cookie_alg_descr sc_algs[],
const char *name);
/**
* @brief Check whether supplied client and server cookie match.
* @param cookie_opt Entire cookie option, must contain server cookie.
* @param cc Client cookie.
* @param sc Server cookie that should be checked.
* @param sc_len Server cookie length.
* @param check_ctx Data known to the server needed for cookie validation.
* @param sc_alg Server cookie algorithm.
* @return kr_ok() if check OK, error code else.
*/
KR_EXPORT
int kr_srvr_cookie_check(const uint8_t *cookie_opt,
int kr_srvr_cookie_check(const uint8_t cc[KNOT_OPT_COOKIE_CLNT],
const uint8_t *sc, uint16_t sc_len,
const struct kr_srvr_cookie_check_ctx *check_ctx,
const struct kr_srvr_cookie_alg_descr *sc_alg);
......@@ -38,9 +38,16 @@ struct kr_cookie_secret dflt_cs = {
.data = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
/* Default srver secret. */
struct kr_cookie_secret dflt_ss = {
.size = KNOT_OPT_COOKIE_CLNT,
.data = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
struct kr_cookie_ctx kr_glob_cookie_ctx = {
.enabled = false,
.current_cs = &dflt_cs
.current_cs = &dflt_cs,
.current_ss = &dflt_ss
};
static int opt_rr_add_cookies(knot_rrset_t *opt_rr,
......
......@@ -34,6 +34,10 @@ struct kr_cookie_secret {
KR_EXPORT
extern struct kr_cookie_secret dflt_cs;
/** Default server secret. */
KR_EXPORT
extern struct kr_cookie_secret dflt_ss;
/** Default cookie TTL. */
#define DFLT_COOKIE_TTL 72000
......@@ -46,7 +50,11 @@ struct kr_cookie_ctx {
uint32_t cache_ttl; /**< TTL used when caching cookies */
struct kr_cookie_secret *current_ss; /**< current server secret */
struct kr_cookie_secret *recent_ss; /**< recent server secret */
const struct kr_clnt_cookie_alg_descr *cc_alg; /**< Client cookie algorithm. */
const struct kr_srvr_cookie_alg_descr *sc_alg; /**< Server cookie algorithm. */
};
/** Global cookie control context. */
......
......@@ -26,6 +26,7 @@
#include "daemon/engine.h"
#include "lib/cookies/alg_clnt.h"
#include "lib/cookies/alg_srvr.h"
#include "lib/cookies/cache.h"
#include "lib/cookies/control.h"
#include "lib/module.h"
......@@ -366,12 +367,85 @@ static int check_response(knot_layer_t *ctx, knot_pkt_t *pkt)
return ctx->state;
}
static int check_request(knot_layer_t *ctx, void *module_param)
{
if (!kr_glob_cookie_ctx.enabled) {
/* TODO -- IS there a way how to determine whether the original
* request came via TCP? */
return ctx->state;
}
struct kr_request *req = ctx->data;
const knot_rrset_t *req_opt_rr = req->qsource.opt;
if (!req_opt_rr) {
return ctx->state;
}
uint8_t *req_cookie_opt = knot_edns_get_option(req_opt_rr,
KNOT_EDNS_OPTION_COOKIE);
if (!req_cookie_opt) {
return ctx->state;
}
const uint8_t *req_cookie_data = knot_edns_opt_get_data(req_cookie_opt);
uint16_t req_cookie_len = knot_edns_opt_get_length(req_cookie_opt);
assert(req_cookie_data && req_cookie_len);
const uint8_t *req_cc = NULL, *req_sc = NULL;
uint16_t req_cc_len = 0, req_sc_len = 0;
int ret = knot_edns_opt_cookie_parse(req_cookie_data, req_cookie_len,
&req_cc, &req_cc_len,
&req_sc, &req_sc_len);
if (ret != KNOT_EOK) {
/* TODO -- Generate BADCOOKIE response. */
DEBUG_MSG(NULL, "%s\n", "got malformed DNS cookie in request");
return ctx->state;
}
assert(req_cc_len == KNOT_OPT_COOKIE_CLNT);
if (!req_sc) {
/* TODO -- BADCOOKIE? Occasionally ignore? */
DEBUG_MSG(NULL, "%s\n", "no server cookie in request");
return ctx->state;
}
/* Check server cookie obtained in request. */
const struct kr_cookie_ctx *cntrl = &kr_glob_cookie_ctx;
if (!req->qsource.addr || !cntrl->current_ss) {
/* TODO -- SERVFAIL? */
DEBUG_MSG(NULL, "%s\n", "no server DNS cookie context data");
return ctx->state;
}
struct kr_srvr_cookie_check_ctx check_ctx = {
.clnt_sockaddr = req->qsource.addr,
.secret_data = cntrl->current_ss->data,
.secret_len = cntrl->current_ss->size
};
ret = kr_srvr_cookie_check(req_cc, req_sc, req_sc_len, &check_ctx,
cntrl->sc_alg);
if (ret != kr_ok()) {
/* TODO -- BADCOOKIE? Occasionally ignore? */
DEBUG_MSG(NULL, "%s\n", "invalid server DNS cookie data");
return ctx->state;
}
/* Server cookie OK. */
return ctx->state;
}
/** Module implementation. */
KR_EXPORT
const knot_layer_api_t *cookiemonster_layer(struct kr_module *module)
{
static knot_layer_api_t _layer = {
.begin = &check_request,
.consume = &check_response
};
/* Store module reference */
......
......@@ -114,6 +114,9 @@ struct kr_request {
const struct sockaddr *addr;
const struct sockaddr *dst_addr;
const knot_pkt_t *packet;
#if defined(ENABLE_COOKIES)
const knot_rrset_t *opt;
#endif /* defined(ENABLE_COOKIES) */
} qsource;
struct {
unsigned rtt; /**< Current upstream RTT */
......
......@@ -22,6 +22,7 @@
#include "daemon/engine.h"
#include "lib/cookies/alg_clnt.h"
#include "lib/cookies/alg_srvr.h"
#include "lib/cookies/control.h"
#include "lib/layer.h"
......@@ -291,7 +292,9 @@ 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.current_ss = &dflt_ss;
kr_glob_cookie_ctx.cc_alg = kr_clnt_cookie_alg(kr_clnt_cookie_algs, "FNV-64");
kr_glob_cookie_ctx.sc_alg = kr_srvr_cookie_alg(kr_srvr_cookie_algs, "HMAC-SHA256-64");
module->data = NULL;
......@@ -315,6 +318,18 @@ int cookiectl_deinit(struct kr_module *module)
}
kr_glob_cookie_ctx.current_cs = &dflt_cs;
if (kr_glob_cookie_ctx.recent_ss &&
kr_glob_cookie_ctx.recent_ss != &dflt_ss) {
free(kr_glob_cookie_ctx.recent_ss);
}
kr_glob_cookie_ctx.recent_ss = NULL;
if (kr_glob_cookie_ctx.current_ss &&
kr_glob_cookie_ctx.current_ss != &dflt_ss) {
free(kr_glob_cookie_ctx.current_ss);
}
kr_glob_cookie_ctx.current_ss = &dflt_ss;
return kr_ok();
}
......
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