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

TSIG AXFR: buffer unsigned messages up to 100 packets

parent 1f6714e5
No related branches found
No related tags found
No related merge requests found
......@@ -39,8 +39,7 @@ struct process_answer_param {
tsig_ctx_t tsig_ctx;
};
struct answer_data
{
struct answer_data {
/* Extensions. */
void *ext;
void (*ext_cleanup)(struct answer_data*); /*!< Extensions cleanup callback. */
......
......@@ -23,6 +23,11 @@
#include "libknot/tsig-op.h"
#include "knot/nameserver/tsig_ctx.h"
/*!
* Maximal total size for unsigned messages.
*/
static const size_t TSIG_BUFFER_MAX_SIZE = (UINT16_MAX * 100);
void tsig_init(tsig_ctx_t *ctx, const knot_tsig_key_t *key)
{
if (!ctx) {
......@@ -33,6 +38,16 @@ void tsig_init(tsig_ctx_t *ctx, const knot_tsig_key_t *key)
ctx->key = key;
}
void tsig_cleanup(tsig_ctx_t *ctx)
{
if (!ctx) {
return;
}
free(ctx->buffer);
memset(ctx, 0, sizeof(*ctx));
}
int tsig_sign_packet(tsig_ctx_t *ctx, knot_pkt_t *packet)
{
if (!ctx || !packet) {
......@@ -75,6 +90,36 @@ static int update_ctx_after_verify(tsig_ctx_t *ctx, knot_rrset_t *tsig_rr)
memcpy(ctx->digest, tsig_rdata_mac(tsig_rr), ctx->digest_size);
ctx->prev_signed_time = tsig_rdata_time_signed(tsig_rr);
ctx->unsigned_count = 0;
ctx->buffer_used = 0;
return KNOT_EOK;
}
static int buffer_add_packet(tsig_ctx_t *ctx, knot_pkt_t *packet)
{
size_t need = ctx->buffer_used + packet->size;
// Inflate the buffer if necessary.
if (need > TSIG_BUFFER_MAX_SIZE) {
return KNOT_ENOMEM;
}
if (need > ctx->buffer_size) {
uint8_t *buffer = realloc(ctx->buffer, need);
if (!buffer) {
return KNOT_ENOMEM;
}
ctx->buffer = buffer;
ctx->buffer_size = need;
}
// Buffer the packet.
uint8_t *write = ctx->buffer + ctx->buffer_used;
memcpy(write, packet->wire, packet->size);
ctx->buffer_used = need;
return KNOT_EOK;
}
......@@ -89,19 +134,27 @@ int tsig_verify_packet(tsig_ctx_t *ctx, knot_pkt_t *packet)
return KNOT_EOK;
}
int ret = buffer_add_packet(ctx, packet);
if (ret != KNOT_EOK) {
return ret;
}
// Unsigned packet.
if (packet->tsig_rr == NULL) {
ctx->unsigned_count += 1;
return KNOT_EOK;
}
int ret = KNOT_ERROR;
// Signed packet.
if (ctx->prev_signed_time == 0) {
ret = knot_tsig_client_check(packet->tsig_rr, packet->wire,
packet->size, ctx->digest,
ret = knot_tsig_client_check(packet->tsig_rr, ctx->buffer,
ctx->buffer_used, ctx->digest,
ctx->digest_size, ctx->key, 0);
} else {
ret = knot_tsig_client_check_next(packet->tsig_rr, packet->wire,
packet->size, ctx->digest,
ret = knot_tsig_client_check_next(packet->tsig_rr, ctx->buffer,
ctx->buffer_used, ctx->digest,
ctx->digest_size, ctx->key,
ctx->prev_signed_time);
}
......
......@@ -30,11 +30,16 @@
*/
typedef struct tsig_ctx {
const knot_tsig_key_t *key;
uint64_t prev_signed_time;
uint8_t digest[TSIG_MAX_DIGEST_SIZE];
size_t digest_size;
uint64_t prev_signed_time;
/* Unsigned packets handling. */
unsigned unsigned_count;
uint8_t *buffer;
size_t buffer_used;
size_t buffer_size;
} tsig_ctx_t;
/*!
......@@ -46,6 +51,13 @@ typedef struct tsig_ctx {
*/
void tsig_init(tsig_ctx_t *ctx, const knot_tsig_key_t *key);
/*!
* \brief Cleanup TSIG context.
*
* \param ctx TSIG context to be cleaned up.
*/
void tsig_cleanup(tsig_ctx_t *ctx);
/*!
* \brief Sign outgoing packet.
*
......
......@@ -111,6 +111,10 @@ static int zone_query_execute(zone_t *zone, uint16_t pkt_type, const conf_iface_
knot_pkt_put(query, COMPR_HINT_QNAME, &soa_rr, 0);
}
/* Create requestor instance. */
struct requestor re;
requestor_init(&re, NS_PROC_ANSWER, &mm);
/* Answer processing parameters. */
struct process_answer_param param = { 0 };
param.zone = zone;
......@@ -120,19 +124,14 @@ static int zone_query_execute(zone_t *zone, uint16_t pkt_type, const conf_iface_
ret = tsig_sign_packet(&param.tsig_ctx, query);
if (ret != KNOT_EOK) {
mp_delete(mm.ctx);
return ret;
goto fail;
}
/* Create requestor instance. */
struct requestor re;
requestor_init(&re, NS_PROC_ANSWER, &mm);
/* Create a request. */
struct request *req = requestor_make(&re, remote, query);
if (req == NULL) {
mp_delete(mm.ctx);
return KNOT_ENOMEM;
ret = KNOT_ENOMEM;
goto fail;
}
/* Send the queries and process responses. */
......@@ -142,7 +141,9 @@ static int zone_query_execute(zone_t *zone, uint16_t pkt_type, const conf_iface_
ret = requestor_exec(&re, &tv);
}
fail:
/* Cleanup. */
tsig_cleanup(&param.tsig_ctx);
requestor_clear(&re);
mp_delete(mm.ctx);
......
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