Commit 0283796c authored by Daniel Salzman's avatar Daniel Salzman

Merge branch 'tsig-bug' of /git/repositories/knot

parents e77cba6f 739060b2
......@@ -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,15 +389,20 @@ 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) {
if (tsig_req && tsig == NULL) {
// TSIG missing!!
return KNOT_EMALF;
return KNOT_ENOTSIG;
} else if (tsig != NULL) {
// TSIG there, either required or not, process
if (xfr->packet_nr == 0) {
......@@ -894,7 +899,7 @@ dbg_xfrin_exec_verb(
/* Now check if there is not a TSIG record at the end of the packet. */
ret = xfrin_check_tsig(packet, xfr,
knot_ns_tsig_required(xfr->packet_nr));
++xfr->packet_nr;
//++xfr->packet_nr;
knot_packet_free(&packet);
dbg_xfrin_verb("Processed one AXFR packet successfully.\n");
......
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