Skip to content
Snippets Groups Projects
Commit cdcdc93e authored by Jan Včelák's avatar Jan Včelák :rocket:
Browse files

requestor: support for TSIG verification

parent f184e00d
No related branches found
No related tags found
No related merge requests found
......@@ -29,6 +29,7 @@ enum knot_layer_state {
KNOT_STATE_NOOP = 0, //!< Invalid.
KNOT_STATE_CONSUME, //!< Consume data.
KNOT_STATE_PRODUCE, //!< Produce data.
KNOT_STATE_RESET, //!< Restart processing.
KNOT_STATE_DONE, //!< Finished.
KNOT_STATE_FAIL //!< Error.
};
......
......@@ -105,6 +105,7 @@ struct knot_request *knot_request_make(knot_mm_t *mm,
const struct sockaddr *remote,
const struct sockaddr *source,
knot_pkt_t *query,
const knot_tsig_key_t *tsig_key,
unsigned flags)
{
if (remote == NULL || query == NULL) {
......@@ -133,6 +134,8 @@ struct knot_request *knot_request_make(knot_mm_t *mm,
request->source.ss_family = AF_UNSPEC;
}
tsig_init(&request->tsig, tsig_key);
return request;
}
......@@ -147,6 +150,7 @@ void knot_request_free(struct knot_request *request, knot_mm_t *mm)
}
knot_pkt_free(&request->query);
knot_pkt_free(&request->resp);
tsig_cleanup(&request->tsig);
mm_free(mm, request);
}
......@@ -163,7 +167,7 @@ int knot_requestor_init(struct knot_requestor *requestor,
requestor->mm = mm;
knot_layer_init(&requestor->layer, mm, proc);
requestor->layer.state = knot_layer_begin(&requestor->layer, proc_param);
knot_layer_begin(&requestor->layer, proc_param);
return KNOT_EOK;
}
......@@ -179,53 +183,89 @@ void knot_requestor_clear(struct knot_requestor *requestor)
memset(requestor, 0, sizeof(*requestor));
}
static int request_io(struct knot_requestor *req, struct knot_request *last,
int timeout_ms)
static int request_reset(struct knot_requestor *req,
struct knot_request *last)
{
int ret = KNOT_EOK;
knot_pkt_t *query = last->query;
knot_pkt_t *resp = last->resp;
knot_layer_reset(&req->layer);
tsig_reset(&last->tsig);
if (req->layer.state == KNOT_STATE_RESET) {
return KNOT_LAYER_ERROR;
}
/* Data to be sent. */
if (req->layer.state == KNOT_STATE_PRODUCE) {
return KNOT_EOK;
}
/* Process query and send it out. */
knot_layer_produce(&req->layer, query);
static int request_produce(struct knot_requestor *req,
struct knot_request *last,
int timeout_ms)
{
knot_layer_produce(&req->layer, last->query);
if (req->layer.state == KNOT_STATE_CONSUME) {
ret = request_send(last, timeout_ms);
if (ret != KNOT_EOK) {
return ret;
}
}
int ret = tsig_sign_packet(&last->tsig, last->query);
if (ret != KNOT_EOK) {
return ret;
}
/* Data to be read. */
// TODO: verify condition
if (req->layer.state == KNOT_STATE_CONSUME) {
/* Read answer and process it. */
ret = request_recv(last, timeout_ms);
if (ret < 0) {
return ret;
}
ret = request_send(last, timeout_ms);
}
return ret;
}
(void) knot_pkt_parse(resp, 0);
knot_layer_consume(&req->layer, resp);
static int request_consume(struct knot_requestor *req,
struct knot_request *last,
int timeout_ms)
{
int ret = request_recv(last, timeout_ms);
if (ret < 0) {
return ret;
}
ret = knot_pkt_parse(last->resp, 0);
if (ret != KNOT_EOK) {
return ret;
}
ret = tsig_verify_packet(&last->tsig, last->resp);
if (ret != KNOT_EOK) {
return ret;
}
knot_layer_consume(&req->layer, last->resp);
return KNOT_EOK;
}
static bool layer_active(enum knot_layer_state state)
{
switch (state) {
case KNOT_STATE_PRODUCE:
case KNOT_STATE_CONSUME:
case KNOT_STATE_PRODUCE:
case KNOT_STATE_RESET:
return true;
default:
return false;
}
}
static int request_io(struct knot_requestor *req, struct knot_request *last,
int timeout_ms)
{
switch (req->layer.state) {
case KNOT_STATE_CONSUME:
return request_consume(req, last, timeout_ms);
case KNOT_STATE_PRODUCE:
return request_produce(req, last, timeout_ms);
case KNOT_STATE_RESET:
return request_reset(req, last);
default:
return KNOT_EINVAL;
}
}
int knot_requestor_exec(struct knot_requestor *requestor,
struct knot_request *request,
int timeout_ms)
......@@ -240,7 +280,7 @@ int knot_requestor_exec(struct knot_requestor *requestor,
while (layer_active(requestor->layer.state)) {
ret = request_io(requestor, request, timeout_ms);
if (ret != KNOT_EOK) {
knot_layer_reset(&requestor->layer);
knot_layer_finish(&requestor->layer);
return ret;
}
}
......@@ -250,8 +290,13 @@ int knot_requestor_exec(struct knot_requestor *requestor,
ret = KNOT_LAYER_ERROR;
}
/* Verify last TSIG */
if (tsig_unsigned_count(&request->tsig) != 0) {
ret = KNOT_LAYER_ERROR;
}
/* Finish current query processing. */
knot_layer_reset(&requestor->layer);
knot_layer_finish(&requestor->layer);
return ret;
}
......@@ -19,6 +19,7 @@
#include <sys/socket.h>
#include <sys/time.h>
#include "knot/nameserver/tsig_ctx.h"
#include "knot/query/layer.h"
#include "libknot/mm_ctx.h"
#include "libknot/rrtype/tsig.h"
......@@ -46,7 +47,9 @@ struct knot_request {
struct sockaddr_storage remote, source;
knot_pkt_t *query;
knot_pkt_t *resp;
knot_sign_context_t sign;
tsig_ctx_t tsig;
knot_sign_context_t sign; // TODO: WIPE?
knot_layer_t layer;
};
/*!
......@@ -56,6 +59,7 @@ struct knot_request {
* \param dst Remote endpoint address.
* \param src Source address (or NULL).
* \param query Query message.
* \param key TSIG key for authentication.
* \param flags Request flags.
*
* \return Prepared request or NULL in case of error.
......@@ -64,6 +68,7 @@ struct knot_request *knot_request_make(knot_mm_t *mm,
const struct sockaddr *dst,
const struct sockaddr *src,
knot_pkt_t *query,
const knot_tsig_key_t *key,
unsigned flags);
/*!
......
......@@ -34,7 +34,7 @@
* but simply if the requesting/receiving works, so mirror is okay. */
static int reset(knot_layer_t *ctx) { return KNOT_STATE_PRODUCE; }
static int begin(knot_layer_t *ctx, void *module_param) { return reset(ctx); }
static int finish(knot_layer_t *ctx) { return KNOT_STATE_NOOP; }
static int finish(knot_layer_t *ctx) { return reset(ctx); }
static int in(knot_layer_t *ctx, knot_pkt_t *pkt) { return KNOT_STATE_DONE; }
static int out(knot_layer_t *ctx, knot_pkt_t *pkt) { return KNOT_STATE_CONSUME; }
......@@ -42,8 +42,7 @@ static const int TIMEOUT = 2000;
/*! \brief Dummy answer processing module. */
const knot_layer_api_t dummy_module = {
&begin, &reset, &finish,
&in, &out, NULL
&begin, &reset, &finish, &in, &out, NULL
};
static void set_blocking_mode(int sock)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment