Skip to content
Snippets Groups Projects
Commit 7e8c9a8f authored by Marek Vavruša's avatar Marek Vavruša
Browse files

layer/iterate: do DNS 0x20 unless in safe mode

DNS 0x20 https://tools.ietf.org/html/draft-vixie-dnsext-dns0x20-00
is a way to add more randomness into queries to make spoofing tougher
this implementation provides up to 32 bits of randomness to QNAME,
which is more than enough for most names (it is possible to add a
maximum of 1 bit of entropy per alphanumeric character, so it's not very
efficient with shorter names)

fixes #27
parent fefa311a
Branches
Tags
No related merge requests found
......@@ -14,6 +14,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <ctype.h>
#include <sys/time.h>
#include <libknot/descriptor.h>
......@@ -56,11 +57,39 @@ static const knot_dname_t *minimized_qname(struct kr_query *query, uint16_t *qty
return qname;
}
/* Randomize QNAME letter case.
* This adds 32 bits of randomness at maximum, but that's more than an average domain name length.
* https://tools.ietf.org/html/draft-vixie-dnsext-dns0x20-00
*/
static void randomized_qname_case(knot_dname_t *qname, unsigned secret)
{
unsigned k = 0;
while (*qname != '\0') {
for (unsigned i = *qname; i--;) {
int chr = qname[i + 1];
if (isalpha(chr)) {
if (secret & (1 << k)) {
qname[i + 1] ^= 0x20;
}
k = (k + 1) % (sizeof(secret) * CHAR_BIT);
}
}
qname = (uint8_t *)knot_wire_next_label(qname, NULL);
}
}
/** Answer is paired to query. */
static bool is_paired_to_query(const knot_pkt_t *answer, struct kr_query *query)
{
uint16_t qtype = query->stype;
const knot_dname_t *qname = minimized_qname(query, &qtype);
const knot_dname_t *qname_min = minimized_qname(query, &qtype);
/* Construct expected randomized QNAME */
uint8_t qname[KNOT_DNAME_MAXLEN];
knot_dname_to_wire(qname, qname_min, sizeof(qname));
if (!(query->flags & QUERY_CACHED)) {
randomized_qname_case(qname, query->secret);
}
return query->id == knot_wire_get_id(answer->wire) &&
(query->sclass == KNOT_CLASS_ANY || query->sclass == knot_pkt_qclass(answer)) &&
......@@ -353,6 +382,11 @@ int kr_make_query(struct kr_query *query, knot_pkt_t *pkt)
return ret;
}
/* Randomize query case (if not in safemode) */
query->secret = (query->flags & QUERY_SAFEMODE) ? 0 : kr_rand_uint(UINT32_MAX);
knot_dname_t *qname_raw = (knot_dname_t *)knot_pkt_qname(pkt);
randomized_qname_case(qname_raw, query->secret);
/* Query built, expect answer. */
query->id = kr_rand_uint(UINT16_MAX);
knot_wire_set_id(pkt->wire, query->id);
......@@ -428,6 +462,10 @@ static int resolve(knot_layer_t *ctx, knot_pkt_t *pkt)
return KNOT_STATE_DONE;
}
/* Packet cleared, normalize QNAME. */
knot_dname_t *qname_raw = (knot_dname_t *)knot_pkt_qname(pkt);
knot_dname_to_lower(qname_raw);
/* Check response code. */
#ifndef NDEBUG
lookup_table_t *rcode = lookup_by_id(knot_rcode_names, knot_wire_get_rcode(pkt->wire));
......
......@@ -61,6 +61,7 @@ struct kr_query {
uint16_t sclass;
uint16_t id;
uint16_t flags;
unsigned secret;
};
/**
......
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