Commit 739060b2 authored by Marek Vavrusa's avatar Marek Vavrusa

Fixed TSIG check for multi-packet signatures.

Problem was the function is copied from another one which
always decrements the arcount and trims the TSIG RR. But with
aggregated responses, this should be stripped not from first,
but from the packet actually containing the TSIG.
parent 3977f048
......@@ -2509,6 +2509,10 @@ typedef struct ns_axfr_params {
int knot_ns_tsig_required(int packet_nr)
{
/*! \bug This can overflow to negative numbers. Proper solution is to
* count exactly at one place for each incoming/outgoing packet
* with packet_nr = (packet_nr + 1) % FREQ and require TSIG on 0.
*/
dbg_ns_verb("ns_tsig_required(%d): %d\n", packet_nr,
(packet_nr % KNOT_NS_TSIG_FREQ == 0));
return (packet_nr % KNOT_NS_TSIG_FREQ == 0);
......
......@@ -679,6 +679,25 @@ int knot_tsig_sign_next(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
return KNOT_EOK;
}
int knot_tsig_check_prep(uint8_t* wire, size_t *wire_size, const knot_rrset_t *tsig)
{
if (wire == NULL || wire_size == NULL || tsig == NULL) {
return KNOT_EINVAL;
}
/* Trim TSIG from the packet if it contains it. */
size_t tsig_len = tsig_wire_actsize(tsig);
*wire_size -= tsig_len;
/* Restore message id. */
knot_wire_set_id(wire, tsig_rdata_orig_id(tsig));
/* Decrease arcount. */
knot_wire_set_arcount(wire, knot_wire_get_arcount(wire) - 1);
return KNOT_EOK;
}
static int knot_tsig_check_digest(const knot_rrset_t *tsig_rr,
const uint8_t *wire, size_t size,
const uint8_t *request_mac,
......@@ -715,13 +734,6 @@ static int knot_tsig_check_digest(const knot_rrset_t *tsig_rr,
dbg_tsig_verb("TSIG: key validity checked.\n");
/* Time OK algorithm OK, key name OK - do digest. */
/* Calculate the size of TSIG RR. */
size_t tsig_len = tsig_wire_actsize(tsig_rr);
/* Strip the TSIG. */
size -= tsig_len;
uint8_t *wire_to_sign = malloc(sizeof(uint8_t) * size);
if (!wire_to_sign) {
ERR_ALLOC_FAILED;
......@@ -731,23 +743,20 @@ static int knot_tsig_check_digest(const knot_rrset_t *tsig_rr,
memset(wire_to_sign, 0, sizeof(uint8_t) * size);
memcpy(wire_to_sign, wire, size);
/* Restore message id. */
knot_wire_set_id(wire_to_sign, tsig_rdata_orig_id(tsig_rr));
/* Decrease arcount. */
knot_wire_set_arcount(wire_to_sign,
knot_wire_get_arcount(wire_to_sign) - 1);
uint8_t digest_tmp[KNOT_TSIG_MAX_DIGEST_SIZE];
size_t digest_tmp_len = 0;
assert(tsig_rr->rdata);
if (use_times) {
/* Wire is not a single packet, TSIG RRs must be stripped already. */
ret = knot_tsig_create_sign_wire_next(wire_to_sign, size,
request_mac, request_mac_len,
digest_tmp, &digest_tmp_len,
tsig_rr, tsig_key);
} else {
/* Well, here it isn't. Strip the TSIG. */
knot_tsig_check_prep(wire_to_sign, &size, tsig_rr);
ret = knot_tsig_create_sign_wire(wire_to_sign, size,
request_mac, request_mac_len,
digest_tmp, &digest_tmp_len,
......
......@@ -101,6 +101,19 @@ int knot_tsig_sign_next(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
const knot_tsig_key_t *key, uint8_t *to_sign,
size_t to_sign_len);
/*!
* \brief Strip TSIG and restore message ID on the wire.
*
* This is required for computing the digest from the wire for
* checking signature validity.
*
* \param wire
* \param wire_size
* \param tsig
* \return
*/
int knot_tsig_check_prep(uint8_t* wire, size_t *wire_size, const knot_rrset_t *tsig);
/*!
* \brief Checks incoming request.
*
......
......@@ -389,9 +389,14 @@ static int xfrin_check_tsig(knot_packet_t *packet, knot_ns_xfr_t *xfr,
// just append the wireformat to the TSIG data
assert(KNOT_NS_TSIG_DATA_MAX_SIZE - xfr->tsig_data_size
>= xfr->wire_size);
memcpy(xfr->tsig_data + xfr->tsig_data_size,
xfr->wire, xfr->wire_size);
uint8_t *wire_buf = xfr->tsig_data + xfr->tsig_data_size;
memcpy(wire_buf, xfr->wire, xfr->wire_size);
xfr->tsig_data_size += xfr->wire_size;
/* Strip TSIG RR from wire and restore message ID. */
if (tsig) {
knot_tsig_check_prep(wire_buf, &xfr->tsig_data_size, tsig);
}
}
if (xfr->tsig_key) {
......
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