#include "respip/respip.h"
#include "libunbound/context.h"
#include "libunbound/libworker.h"
+#include "sldns/parseutil.h"
#include "sldns/sbuffer.h"
#include "sldns/wire2str.h"
#include "util/shm_side/shm_main.h"
if (check_result.value == RESPONSE_MESSAGE) {
struct reply_info *rep = NULL;
int r;
- const char* tsig_name = "\x19" "foobar-example-dyn-update\x00";
- const size_t tsig_name_len = 27;
+ const char* tsig_name = "\x19""foobar-example-dyn-update\x00";
+ const char* alg = "\x0b""hmac-sha256\x00";
const char* tsig_secret =
"\x59\x2E\xD3\xD0\x84\xA8\x69\x5F\x8C\xCA\x07\xBE\x1B\xFC\x1E\x98\x74\xE7\xF6\x64\x30\x32\x10\xC6\x33\x09\x93\x94\x9D\xF1\x71\x74\x42\x27\xAB\xF5\x11\x59\x0D\x2E\x52\x2F\xBD\xA8\x7E\xD9\xEA\xD6\x8F\x3D\x6F\xD2\x60\x56\xD8\xD3\xCA\x02\xB7\x16\x1C\x43\x6D\xB8";
const size_t tsig_secret_len = 64;
- log_err("RESPONSE received");
if (!worker_check_response(c->buffer, worker)) {
- log_err("Not a suitable response to cache");
+ verbose(VERB_ALGO, "Bad response");
+ log_addr(VERB_CLIENT,"from",&repinfo->client_addr, repinfo->client_addrlen);
comm_point_drop_reply(repinfo);
return 0;
}
- if((r = reply_info_parse(c->buffer, worker->env.alloc, &qinfo,
- &rep, worker->scratchpad, &edns))) {
- log_err("bad response. Will not cache it (%d)", r);
+ if((r = tsig_verify(c->buffer, tsig_name, alg, tsig_secret,
+ tsig_secret_len, *worker->env.now))) {
+ verbose(VERB_ALGO, "worker tsig very of response: %s",
+ sldns_lookup_by_id(sldns_tsig_errors, r)?
+ sldns_lookup_by_id(sldns_tsig_errors, r)->name:"??");
+ log_addr(VERB_CLIENT,"from",&repinfo->client_addr, repinfo->client_addrlen);
comm_point_drop_reply(repinfo);
return 0;
}
- if((r = tsig_verify(c->buffer, tsig_name, tsig_name_len,
- tsig_secret, tsig_secret_len))) {
- log_err("response had wrong TSIG. Will not cache it (%d)", r);
+ if((r = reply_info_parse(c->buffer, worker->env.alloc, &qinfo,
+ &rep, worker->scratchpad, &edns))) {
+ verbose(VERB_ALGO, "worker parse response: %s",
+ sldns_lookup_by_id(sldns_rcodes, r)?
+ sldns_lookup_by_id(sldns_rcodes, r)->name:"??");
+ log_addr(VERB_CLIENT,"from",&repinfo->client_addr, repinfo->client_addrlen);
comm_point_drop_reply(repinfo);
return 0;
}
#include "util/data/msgparse.h"
#include "util/data/dname.h"
#include <openssl/evp.h>
+#include <openssl/hmac.h>
/**
* out 0 on success, an error code otherwise.
*/
int
-tsig_verify(sldns_buffer* pkt, const uint8_t* name, size_t name_len,
- const uint8_t* secret, size_t secret_len)
+tsig_verify(sldns_buffer* pkt, const uint8_t* name, const uint8_t* alg,
+ const uint8_t* secret, size_t secret_len, uint64_t now)
{
size_t n_rrs;
+ size_t end_of_message;
uint16_t rdlength;
uint8_t mac[1024];
- uint16_t mac_size;
+ uint16_t mac_sz;
uint8_t hmac_result[1024];
- size_t hmac_result_len;
+ unsigned int hmac_result_len;
size_t pos;
uint16_t other_len;
size_t algname_size;
+ uint64_t time_signed;
+ uint16_t fudge;
const EVP_MD* digester;
assert(LDNS_QDCOUNT(sldns_buffer_begin(pkt)) == 1);
if(LDNS_ARCOUNT(sldns_buffer_begin(pkt)) < 1) {
- log_err("No TSIG found (not in ARCOUNT)");
+ log_err("No TSIG found (ARCOUNT == 0)");
return -1;
}
LDNS_ARCOUNT_SET( sldns_buffer_begin(pkt)
sldns_buffer_rewind(pkt);
sldns_buffer_skip(pkt, LDNS_HEADER_SIZE);
- pkt_dname_len(pkt); /* skip qname */
- sldns_buffer_skip(pkt, 2 * sizeof(uint16_t));
- if(sldns_buffer_remaining(pkt) < sizeof(uint16_t))
+ pkt_dname_len(pkt); /* skip qname */
+ sldns_buffer_skip(pkt, 2 * sizeof(uint16_t)); /* skip type and class */
+ if(!skip_pkt_rrs(pkt, n_rrs)) /* skip all rrs */
return -1;
- if(!skip_pkt_rrs(pkt, n_rrs))
- return -1;
- pkt_dname_len(pkt); /* skip TSIG name (TODO, compare with name) */
- pos = sldns_buffer_position(pkt); /* Append pos */
+ end_of_message = sldns_buffer_position(pkt);
+ if(query_dname_compare(name, sldns_buffer_current(pkt)))
+ return LDNS_TSIG_ERROR_BADKEY;
+ pkt_dname_len(pkt); /* skip TSIG name */
+ pos = sldns_buffer_position(pkt); /* Append pos */
if(sldns_buffer_read_u16(pkt) != LDNS_RR_TYPE_TSIG) {
log_err("No TSIG found!");
return -1;
}
- sldns_buffer_skip(pkt, sizeof(uint16_t) + sizeof(uint32_t)); /* skip class + TTL */
- rdlength = sldns_buffer_read_u16(pkt);
- algname_size = pkt_dname_len(pkt);
- sldns_buffer_skip(pkt, 8); /* skip time signed and fudge */
- mac_size = sldns_buffer_read_u16(pkt);
- memcpy(mac, sldns_buffer_current(pkt), mac_size);
- sldns_buffer_skip(pkt, mac_size);
+ sldns_buffer_skip(pkt, sizeof(uint16_t) /* skip class */
+ + sizeof(uint32_t) /* skip TTLS */
+ + sizeof(uint16_t)); /* skip rdlength */
+ if(query_dname_compare(alg, sldns_buffer_current(pkt)))
+ return LDNS_TSIG_ERROR_BADKEY;
+ algname_size = pkt_dname_len(pkt); /* skip alg name */
+ time_signed = sldns_buffer_read_u48(pkt); /* time signed */
+ fudge = sldns_buffer_read_u16(pkt); /* fudge */
+ mac_sz = sldns_buffer_read_u16(pkt); /* mac size */
+ memcpy(mac,sldns_buffer_current(pkt),mac_sz); /* copy mac */
+ sldns_buffer_skip(pkt, mac_sz); /* skip mac */
/* Set ID to original ID */
sldns_buffer_write_u16_at(pkt, 0, sldns_buffer_read_u16(pkt));
- sldns_buffer_skip(pkt, sizeof(uint16_t)); /* error */
- other_len = sldns_buffer_read_u16(pkt);
+ sldns_buffer_skip(pkt, sizeof(uint16_t)); /* skip error */
+ other_len = sldns_buffer_read_u16(pkt); /* other len */
- /* move CLASS and TTL -> TYPE position */
+ /* move CLASS (uint16_t) and TTL (uint32_t) -> TYPE position */
memmove( sldns_buffer_at(pkt, pos)
- , sldns_buffer_at(pkt, pos + 2)
+ , sldns_buffer_at(pkt, pos + sizeof(uint16_t) /* type */)
, sizeof(uint16_t) + sizeof(uint32_t));
pos += sizeof(uint16_t) + sizeof(uint32_t);
- /* Append Algorithm Name, Time signed, Fudge */
+ /* Append Algorithm Name, Time signed (uint48_t), Fudge (uint16_t) */
memmove( sldns_buffer_at(pkt, pos)
- , sldns_buffer_at(pkt, pos + 4)
+ , sldns_buffer_at(pkt, pos + sizeof(uint16_t) /* type */
+ + sizeof(uint16_t) /* rdlength */)
, algname_size + 6 /* sizeof(uint48_t) */ + sizeof(uint16_t));
pos += algname_size + 6 /* sizeof(uint48_t) */ + sizeof(uint16_t);
- /* Append Error, Other Len, Other Data */
+ /* Append Error (uint16_t), Other Len (uint16_t), Other Data */
memmove( sldns_buffer_at(pkt, pos)
- , sldns_buffer_at(pkt, sldns_buffer_position(pkt) - 4)
- , 4 + other_len);
- pos += 4 + other_len;
+ , sldns_buffer_at(pkt, sldns_buffer_position(pkt)
+ - 2 * sizeof(uint16_t))
+ , 2 * sizeof(uint16_t) + other_len);
+ pos += 2 * sizeof(uint16_t) + other_len;
digester = EVP_sha256();
hmac_result_len = sizeof(hmac_result);
HMAC( digester, secret, secret_len, sldns_buffer_begin(pkt), pos
- , &hmac_result, &hmac_result_len);
+ , hmac_result, &hmac_result_len);
if(memcmp(mac, hmac_result, hmac_result_len) == 0) {
- log_err("Correct TSIG found (YAY!), MAC size: %d", mac_size);
+ return now > time_signed ?
+ ( time_signed - now > fudge ? LDNS_TSIG_ERROR_BADTIME : 0 )
+ : now - time_signed > fudge ? LDNS_TSIG_ERROR_BADTIME : 0 ;
+ sldns_buffer_set_position(pkt, end_of_message);
return 0;
}
- log_err("TSIG verification failed!");
- return -1;
+ return LDNS_TSIG_ERROR_BADSIG;
}