Commit 731b3cf1 authored by Marek Vavrusa's avatar Marek Vavrusa

Reworked TSIG RR API to work with inline RDATA dnames.

Not much refactoring done, just that the algorithm name must be
known in advance, so a correct RDATA length can be calculated.
parent 6e3382e9
......@@ -283,7 +283,7 @@ static int tsig_parse_str(knot_tsig_key_t *key, const char *str)
if (s) {
*s++ = '\0'; /* Last part separator */
knot_lookup_table_t *alg = NULL;
alg = knot_lookup_by_name(knot_tsig_alg_domain_names, h);
alg = knot_lookup_by_name(knot_tsig_alg_dnames_str, h);
if (alg) {
algorithm = alg->id;
} else {
......
......@@ -58,7 +58,7 @@ knot_lookup_table_t knot_tsig_alg_names[] = {
{ KNOT_TSIG_ALG_NULL, NULL }
};
knot_lookup_table_t knot_tsig_alg_domain_names[] = {
knot_lookup_table_t knot_tsig_alg_dnames_str[] = {
{ KNOT_TSIG_ALG_GSS_TSIG, "gss-tsig." },
{ KNOT_TSIG_ALG_HMAC_MD5, "hmac-md5.sig-alg.reg.int." },
{ KNOT_TSIG_ALG_HMAC_SHA1, "hmac-sha1." },
......@@ -69,6 +69,17 @@ knot_lookup_table_t knot_tsig_alg_domain_names[] = {
{ KNOT_TSIG_ALG_NULL, NULL }
};
knot_lookup_table_t knot_tsig_alg_dnames[] = {
{ KNOT_TSIG_ALG_GSS_TSIG, "\x08" "gss-tsig" },
{ KNOT_TSIG_ALG_HMAC_MD5, "\x08" "hmac-md5" "\x07" "sig-alg" "\x03" "reg" "\x03" "int" },
{ KNOT_TSIG_ALG_HMAC_SHA1, "\x09" "hmac-sha1" },
{ KNOT_TSIG_ALG_HMAC_SHA224, "\x0B" "hmac-sha224" },
{ KNOT_TSIG_ALG_HMAC_SHA256, "\x0B" "hmac-sha256" },
{ KNOT_TSIG_ALG_HMAC_SHA384, "\x0B" "hmac-sha384" },
{ KNOT_TSIG_ALG_HMAC_SHA512, "\x0B" "hmac-sha512" },
{ KNOT_TSIG_ALG_NULL, NULL }
};
size_t knot_tsig_digest_length(const uint8_t algorithm)
{
switch (algorithm) {
......
......@@ -193,7 +193,12 @@ extern knot_lookup_table_t knot_tsig_alg_names[];
/*!
* \brief TSIG key algorithm names in a domain form.
*/
extern knot_lookup_table_t knot_tsig_alg_domain_names[];
extern knot_lookup_table_t knot_tsig_alg_dnames_str[];
/*!
* \brief TSIG key algorithm domain names.
*/
extern knot_lookup_table_t knot_tsig_alg_dnames[];
/*!
* \brief Returns length of TSIG digest for given algorithm.
......
......@@ -466,11 +466,11 @@ int knot_tsig_sign(uint8_t *msg, size_t *msg_len,
}
/* Create rdata for TSIG RR. */
tsig_create_rdata(tmp_tsig, knot_tsig_digest_length(key->algorithm),
(tsig_rcode == KNOT_RCODE_BADTIME)
? tsig_rcode
: 0);
tsig_rdata_set_alg(tmp_tsig, key->algorithm);
uint16_t rdata_rcode = 0;
if (rdata_rcode == KNOT_RCODE_BADTIME)
rdata_rcode = tsig_rcode;
tsig_create_rdata(tmp_tsig, tsig_alg_to_dname(key->algorithm),
knot_tsig_digest_length(key->algorithm), rdata_rcode);
/* Distinguish BADTIME response. */
if (tsig_rcode == KNOT_RCODE_BADTIME) {
......@@ -573,8 +573,8 @@ int knot_tsig_sign_next(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
}
/* Create rdata for TSIG RR. */
tsig_create_rdata(tmp_tsig, knot_tsig_digest_length(key->algorithm), 0);
tsig_rdata_set_alg(tmp_tsig, key->algorithm);
tsig_create_rdata(tmp_tsig, tsig_alg_to_dname(key->algorithm),
knot_tsig_digest_length(key->algorithm), 0);
tsig_rdata_store_current_time(tmp_tsig);
tsig_rdata_set_fudge(tmp_tsig, KNOT_TSIG_FUDGE_DEFAULT);
......@@ -840,35 +840,14 @@ int knot_tsig_add(uint8_t *msg, size_t *msg_len, size_t msg_max_len,
return KNOT_ENOMEM;
}
knot_dname_t *alg_name =
knot_dname_copy(tsig_rdata_alg_name(tsig_rr));
if (alg_name == NULL) {
dbg_tsig("TSIG: failed to copy alg name\n");
knot_rrset_deep_free(&tmp_tsig, 1, 1);
return KNOT_ERROR;
}
/* Create rdata for TSIG RR. */
knot_tsig_algorithm_t alg = tsig_alg_from_name(alg_name);
if (alg == KNOT_TSIG_ALG_NULL) {
dbg_tsig("TSIG: refusing to use NULL algorithm\n");
knot_rrset_deep_free(&tmp_tsig, 1, 1);
knot_dname_free(&alg_name);
return KNOT_ERROR;
}
assert(tsig_rcode != KNOT_RCODE_BADTIME);
tsig_create_rdata(tmp_tsig, 0, tsig_rcode); /* No digest. */
tsig_rdata_set_alg_name(tmp_tsig, alg_name);
tsig_create_rdata(tmp_tsig, tsig_rdata_alg_name(tsig_rr), 0, tsig_rcode);
tsig_rdata_set_time_signed(tmp_tsig, tsig_rdata_time_signed(tsig_rr));
/* Comparing to BIND it was found out that the Fudge should always be
* set to the server's value.
*/
tsig_rdata_set_fudge(tmp_tsig, KNOT_TSIG_FUDGE_DEFAULT);
tsig_rdata_set_mac(tmp_tsig, 0, NULL);
/* Set original ID */
tsig_rdata_set_orig_id(tmp_tsig, knot_wire_get_id(msg));
......
......@@ -43,11 +43,10 @@ typedef enum tsig_off_t {
TSIG_OTHER_O
} tsig_off_t;
/* Helpers for r offset calculation. */
#define TSIG_NAMELEN (sizeof(knot_dname_t*))
/* Helpers for RDATA offset calculation. */
#define TSIG_OTHER_MAXLEN (3 * sizeof(uint16_t))
#define TSIG_OFF_MACLEN (TSIG_NAMELEN + 4 * sizeof(uint16_t))
#define TSIG_FIXED_RDLEN (TSIG_NAMELEN + 11 * sizeof(uint16_t))
#define TSIG_OFF_MACLEN (4 * sizeof(uint16_t))
#define TSIG_FIXED_RDLEN (11 * sizeof(uint16_t))
/*!
* \brief Seek offset of a TSIG RR field.
......@@ -64,12 +63,13 @@ static uint8_t* tsig_rdata_seek(const knot_rrset_t *rr, tsig_off_t id, size_t nb
return NULL;
}
/* Check if fixed part is readable. */
/* TSIG RR names should be already sanitized on parse. */
int alg_len = knot_dname_size(rd);
uint16_t lim = rrset_rdata_item_size(rr, 0);
if (lim < TSIG_NAMELEN + 5 * sizeof(uint16_t)) {
if (lim < alg_len + 5 * sizeof(uint16_t)) {
dbg_tsig("TSIG: rdata: not enough items "
"(has %"PRIu16", min %zu).\n",
lim, TSIG_NAMELEN + 5 * sizeof(uint16_t));
lim, alg_len + 5 * sizeof(uint16_t));
return NULL;
}
......@@ -77,25 +77,25 @@ static uint8_t* tsig_rdata_seek(const knot_rrset_t *rr, tsig_off_t id, size_t nb
uint8_t *bp = rd;
switch(id) {
case TSIG_ALGNAME_O: break;
case TSIG_TSIGNED_O: rd += TSIG_NAMELEN; break;
case TSIG_FUDGE_O: rd += TSIG_NAMELEN + 3 * sizeof(uint16_t); break;
case TSIG_MACLEN_O: rd += TSIG_NAMELEN + 4 * sizeof(uint16_t); break;
case TSIG_MAC_O: rd += TSIG_NAMELEN + 5 * sizeof(uint16_t); break;
case TSIG_TSIGNED_O: rd += alg_len; break;
case TSIG_FUDGE_O: rd += alg_len + 3 * sizeof(uint16_t); break;
case TSIG_MACLEN_O: rd += alg_len + 4 * sizeof(uint16_t); break;
case TSIG_MAC_O: rd += alg_len + 5 * sizeof(uint16_t); break;
case TSIG_ORIGID_O:
rd += TSIG_NAMELEN + 4 * sizeof(uint16_t);
rd += alg_len + 4 * sizeof(uint16_t);
rd += knot_wire_read_u16(rd) + sizeof(uint16_t);
break;
case TSIG_ERROR_O:
rd += TSIG_NAMELEN + 4 * sizeof(uint16_t);
rd += alg_len + 4 * sizeof(uint16_t);
rd += knot_wire_read_u16(rd) + 2 * sizeof(uint16_t);
break;
case TSIG_OLEN_O:
rd += TSIG_NAMELEN + 4 * sizeof(uint16_t);
rd += alg_len + 4 * sizeof(uint16_t);
rd += knot_wire_read_u16(rd) + 3 * sizeof(uint16_t);
break;
case TSIG_OTHER_O:
rd += TSIG_NAMELEN + 4 * sizeof(uint16_t);
rd += alg_len + 4 * sizeof(uint16_t);
rd += knot_wire_read_u16(rd) + 4 * sizeof(uint16_t);
break;
}
......@@ -121,22 +121,26 @@ static int tsig_rdata_set_tsig_error(knot_rrset_t *tsig, uint16_t tsig_error)
return KNOT_EOK;
}
int tsig_create_rdata(knot_rrset_t *rr, uint16_t maclen, uint16_t tsig_err)
int tsig_create_rdata(knot_rrset_t *rr, const knot_dname_t *alg, uint16_t maclen, uint16_t tsig_err)
{
if (!rr) {
if (rr == NULL || alg == NULL) {
return KNOT_EINVAL;
}
/* We already checked rr and know rdlen > 0, no need to check rets. */
size_t rdlen = TSIG_FIXED_RDLEN + maclen;
int alg_len = knot_dname_size(alg);
size_t rdlen = alg_len + TSIG_FIXED_RDLEN + maclen;
if (tsig_err != KNOT_RCODE_BADTIME) {
rdlen -= TSIG_OTHER_MAXLEN;
}
uint8_t *rd = knot_rrset_create_rdata(rr, rdlen);
memset(rd, 0, rdlen);
/* Copy alg name. */
knot_dname_to_wire(rd, alg, rdlen);
/* Set MAC variable length in advance. */
rd += TSIG_OFF_MACLEN;
rd += alg_len + TSIG_OFF_MACLEN;
knot_wire_write_u16(rd, maclen);
/* Set error. */
......@@ -145,24 +149,6 @@ int tsig_create_rdata(knot_rrset_t *rr, uint16_t maclen, uint16_t tsig_err)
return KNOT_EOK;
}
int tsig_rdata_set_alg_name(knot_rrset_t *tsig, knot_dname_t *alg_name)
{
uint8_t *rd = tsig_rdata_seek(tsig, TSIG_ALGNAME_O, TSIG_NAMELEN);
if (!rd) {
return KNOT_ERROR;
}
memcpy(rd, &alg_name, sizeof(knot_dname_t*));
return KNOT_EOK;
}
int tsig_rdata_set_alg(knot_rrset_t *tsig, knot_tsig_algorithm_t alg)
{
const char *s = tsig_alg_to_str(alg);
knot_dname_t *alg_name = knot_dname_from_str(s, strlen(s));
return tsig_rdata_set_alg_name(tsig, alg_name);
}
int tsig_rdata_set_time_signed(knot_rrset_t *tsig, uint64_t time)
{
uint8_t *rd = tsig_rdata_seek(tsig, TSIG_TSIGNED_O, 3*sizeof(uint16_t));
......@@ -234,11 +220,7 @@ int tsig_rdata_set_other_data(knot_rrset_t *tsig, uint16_t len,
const knot_dname_t *tsig_rdata_alg_name(const knot_rrset_t *tsig)
{
uint8_t *rd = tsig_rdata_seek(tsig, TSIG_ALGNAME_O, TSIG_NAMELEN);
if (!rd) {
return NULL;
}
return *((knot_dname_t**)rd);
return knot_rrset_get_rdata(tsig, 0);
}
knot_tsig_algorithm_t tsig_rdata_alg(const knot_rrset_t *tsig)
......@@ -258,7 +240,7 @@ knot_tsig_algorithm_t tsig_rdata_alg(const knot_rrset_t *tsig)
}
knot_lookup_table_t *item = knot_lookup_by_name(
knot_tsig_alg_domain_names, name);
knot_tsig_alg_dnames_str, name);
free(name);
if (!item) {
dbg_tsig("TSIG: rdata: unknown algorithm.\n");
......@@ -352,7 +334,7 @@ int tsig_alg_from_name(const knot_dname_t *alg_name)
}
knot_lookup_table_t *found =
knot_lookup_by_name(knot_tsig_alg_domain_names, name);
knot_lookup_by_name(knot_tsig_alg_dnames_str, name);
if (!found) {
dbg_tsig("Unknown algorithm: %s \n", name);
......@@ -409,7 +391,7 @@ const char* tsig_alg_to_str(knot_tsig_algorithm_t alg)
{
knot_lookup_table_t *item;
item = knot_lookup_by_id(knot_tsig_alg_domain_names, alg);
item = knot_lookup_by_id(knot_tsig_alg_dnames_str, alg);
if (item != NULL) {
return item->name;
......@@ -418,6 +400,19 @@ const char* tsig_alg_to_str(knot_tsig_algorithm_t alg)
}
}
const knot_dname_t* tsig_alg_to_dname(knot_tsig_algorithm_t alg)
{
knot_lookup_table_t *item;
item = knot_lookup_by_id(knot_tsig_alg_dnames, alg);
if (item != NULL) {
return (const knot_dname_t*)item->name;
} else {
return NULL;
}
}
size_t tsig_wire_maxsize(const knot_tsig_key_t *key)
{
size_t alg_name_size = strlen(tsig_alg_to_str(key->algorithm)) + 1;
......
......@@ -55,23 +55,19 @@ enum tsig_consts {
};
/*!
* \note Uses the given domain name, do not deallocate it!
*/
int tsig_create_rdata(knot_rrset_t *rr, uint16_t maclen, uint16_t tsig_err);
/*!
* \brief Set TSIG algorithm name.
*
* \param tsig TSIG RR.
* \param alg_name TSIG name to be assigned.
* \brief Create TSIG RDATA.
*
* \note alg_name is kept and freed with tsig RRSet.
* \param rr TSIG RR to contain created data.
* \param alg Algorithm name.
* \param maclen Algorithm MAC len (may be set to 0 for empty MAC).
* \param tsig_err TSIG error code.
*
* \retval KNOT_EINVAL
* \retval KNOT_EOK
* \retval KNOT_ERROR
*/
int tsig_rdata_set_alg_name(knot_rrset_t *tsig, knot_dname_t *alg_name);
int tsig_rdata_set_alg(knot_rrset_t *tsig, knot_tsig_algorithm_t alg);
int tsig_create_rdata(knot_rrset_t *rr, const knot_dname_t *alg,
uint16_t maclen, uint16_t tsig_err);
int tsig_rdata_set_time_signed(knot_rrset_t *tsig, uint64_t time);
int tsig_rdata_store_current_time(knot_rrset_t *tsig);
int tsig_rdata_set_fudge(knot_rrset_t *tsig, uint16_t fudge);
......@@ -108,6 +104,16 @@ int tsig_alg_from_name(const knot_dname_t *name);
*/
const char* tsig_alg_to_str(knot_tsig_algorithm_t alg);
/*!
* \brief Convert TSIG algorithm identifier to domain name.
*
* \param alg TSIG algorithm identifier.
*
* \retval TSIG algorithm string name.
* \retval Empty string if undefined.
*/
const knot_dname_t* tsig_alg_to_dname(knot_tsig_algorithm_t alg);
/*!
* \brief Return TSIG RRSET maximum wire size for given algorithm.
*
......
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