mirror of https://github.com/getdnsapi/getdns.git
Send TSIG
This commit is contained in:
parent
98dc4018c3
commit
6c1e00fc3f
|
@ -206,7 +206,7 @@ else
|
|||
fi
|
||||
AC_CHECK_HEADERS([openssl/conf.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_HEADERS([openssl/engine.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode])
|
||||
AC_CHECK_FUNCS([OPENSSL_config EVP_md5 EVP_sha1 EVP_sha224 EVP_sha256 EVP_sha384 EVP_sha512 FIPS_mode])
|
||||
AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free,SSL_CTX_set_ecdh_auto], [], [], [
|
||||
AC_INCLUDES_DEFAULT
|
||||
#ifdef HAVE_OPENSSL_ERR_H
|
||||
|
|
|
@ -87,6 +87,19 @@ gldns_write_uint32(void *dst, uint32_t data)
|
|||
}
|
||||
|
||||
|
||||
INLINE void
|
||||
gldns_write_uint48(void *dst, uint64_t data)
|
||||
{
|
||||
uint8_t *p = (uint8_t *) dst;
|
||||
p[0] = (uint8_t) ((data >> 40) & 0xff);
|
||||
p[1] = (uint8_t) ((data >> 32) & 0xff);
|
||||
p[2] = (uint8_t) ((data >> 24) & 0xff);
|
||||
p[3] = (uint8_t) ((data >> 16) & 0xff);
|
||||
p[4] = (uint8_t) ((data >> 8) & 0xff);
|
||||
p[5] = (uint8_t) (data & 0xff);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \file gbuffer.h
|
||||
*
|
||||
|
@ -534,6 +547,20 @@ gldns_buffer_write_u32_at(gldns_buffer *buffer, size_t at, uint32_t data)
|
|||
gldns_write_uint32(buffer->_data + at, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* writes the given 6 byte integer at the given position in the buffer
|
||||
* \param[in] buffer the buffer
|
||||
* \param[in] at the position in the buffer
|
||||
* \param[in] data the (lower) 48 bits to write
|
||||
*/
|
||||
INLINE void
|
||||
gldns_buffer_write_u48_at(gldns_buffer *buffer, size_t at, uint64_t data)
|
||||
{
|
||||
if (buffer->_fixed && at + 6 > buffer->_limit) return;
|
||||
assert(gldns_buffer_available_at(buffer, at, 6));
|
||||
gldns_write_uint48(buffer->_data + at, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* writes the given 4 byte integer at the current position in the buffer
|
||||
* \param[in] buffer the buffer
|
||||
|
@ -546,6 +573,18 @@ gldns_buffer_write_u32(gldns_buffer *buffer, uint32_t data)
|
|||
buffer->_position += sizeof(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* writes the given 6 byte integer at the current position in the buffer
|
||||
* \param[in] buffer the buffer
|
||||
* \param[in] data the 48 bits to write
|
||||
*/
|
||||
INLINE void
|
||||
gldns_buffer_write_u48(gldns_buffer *buffer, uint64_t data)
|
||||
{
|
||||
gldns_buffer_write_u48_at(buffer, buffer->_position, data);
|
||||
buffer->_position += 6;
|
||||
}
|
||||
|
||||
/**
|
||||
* copies count bytes of data at the given position to the given data-array
|
||||
* \param[in] buffer the buffer
|
||||
|
|
|
@ -41,6 +41,26 @@
|
|||
#include "gldns/gbuffer.h"
|
||||
#include "gldns/pkthdr.h"
|
||||
#include "dict.h"
|
||||
#include "debug.h"
|
||||
|
||||
/* MAXIMUM_TSIG_SPACE = TSIG name (dname) : 256
|
||||
* TSIG type (uint16_t) : 2
|
||||
* TSIG class (uint16_t) : 2
|
||||
* TSIG TTL (uint32_t) : 4
|
||||
* RdLen (uint16_t) : 2
|
||||
* Algorithm name (dname) : 256
|
||||
* Time Signed (uint48_t) : 6
|
||||
* Fudge (uint16_t) : 2
|
||||
* Mac Size (uint16_t) : 2
|
||||
* Mac (variable) : EVP_MAX_MD_SIZE
|
||||
* Original Id (uint16_t) : 2
|
||||
* Error (uint16_t) : 2
|
||||
* Other Len (uint16_t) : 2
|
||||
* Other Data (nothing) : 0
|
||||
* ---- +
|
||||
* 538 + EVP_MAX_MD_SIZE
|
||||
*/
|
||||
#define MAXIMUM_TSIG_SPACE (538 + EVP_MAX_MD_SIZE)
|
||||
|
||||
getdns_dict dnssec_ok_checking_disabled_spc = {
|
||||
{ RBTREE_NULL, 0, (int (*)(const void *, const void *)) strcmp },
|
||||
|
@ -249,7 +269,7 @@ _getdns_network_req_add_upstream_option(getdns_network_req * req, uint16_t code,
|
|||
|
||||
/* no overflow allowed for OPT size either (maybe this is overkill
|
||||
given the above check?) */
|
||||
oldlen = gldns_read_uint16(req->opt + 9);
|
||||
oldlen = gldns_read_uint16(req->opt + 9);
|
||||
newlen = oldlen + 4 + sz;
|
||||
if (newlen > UINT16_MAX)
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
|
@ -277,6 +297,98 @@ _getdns_network_req_add_upstream_option(getdns_network_req * req, uint16_t code,
|
|||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
size_t
|
||||
_getdns_network_req_add_tsig(getdns_network_req *req)
|
||||
{
|
||||
getdns_upstream *upstream = req->upstream;
|
||||
gldns_buffer gbuf;
|
||||
uint16_t arcount;
|
||||
const getdns_tsig_info *tsig_info;
|
||||
uint8_t md_buf[EVP_MAX_MD_SIZE];
|
||||
unsigned int md_len = EVP_MAX_MD_SIZE;
|
||||
const EVP_MD *digester;
|
||||
|
||||
if (upstream->tsig_alg == GETDNS_NO_TSIG || !upstream->tsig_dname_len)
|
||||
return req->response - req->query;
|
||||
|
||||
arcount = gldns_read_uint16(req->query + 10);
|
||||
|
||||
#if defined(STUB_DEBUG) && STUB_DEBUG
|
||||
/* TSIG should not have been written yet. */
|
||||
if (req->opt) {
|
||||
assert(arcount == 1);
|
||||
assert(req->opt + 11 + gldns_read_uint16(req->opt + 9)
|
||||
== req->response);
|
||||
} else
|
||||
assert(arcount == 0);
|
||||
#endif
|
||||
tsig_info = _getdns_get_tsig_info(upstream->tsig_alg);
|
||||
|
||||
gldns_buffer_init_frm_data(&gbuf, req->response, MAXIMUM_TSIG_SPACE);
|
||||
gldns_buffer_write(&gbuf,
|
||||
upstream->tsig_dname, upstream->tsig_dname_len); /* Name */
|
||||
gldns_buffer_write_u16(&gbuf, GETDNS_RRCLASS_ANY); /* Class */
|
||||
gldns_buffer_write_u32(&gbuf, 0); /* TTL */
|
||||
gldns_buffer_write(&gbuf,
|
||||
tsig_info->dname, tsig_info->dname_len); /* Algorithm Name */
|
||||
gldns_buffer_write_u48(&gbuf, time(NULL)); /* Time Signed */
|
||||
gldns_buffer_write_u16(&gbuf, 300); /* Fudge */
|
||||
gldns_buffer_write_u16(&gbuf, 0); /* Error */
|
||||
gldns_buffer_write_u16(&gbuf, 0); /* Other len */
|
||||
|
||||
switch (upstream->tsig_alg) {
|
||||
#ifdef HAVE_EVP_MD5
|
||||
case GETDNS_HMAC_MD5 : digester = EVP_md5() ; break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA1
|
||||
case GETDNS_HMAC_SHA1 : digester = EVP_sha1() ; break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA224
|
||||
case GETDNS_HMAC_SHA224: digester = EVP_sha224(); break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA256
|
||||
case GETDNS_HMAC_SHA256: digester = EVP_sha256(); break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA384
|
||||
case GETDNS_HMAC_SHA384: digester = EVP_sha384(); break;
|
||||
#endif
|
||||
#ifdef HAVE_EVP_SHA512
|
||||
case GETDNS_HMAC_SHA512: digester = EVP_sha512(); break;
|
||||
#endif
|
||||
default : return req->response - req->query;
|
||||
}
|
||||
|
||||
(void) HMAC(digester, upstream->tsig_key, upstream->tsig_size,
|
||||
(void *)req->query, gldns_buffer_current(&gbuf) - req->query,
|
||||
md_buf, &md_len);
|
||||
|
||||
gldns_buffer_rewind(&gbuf);
|
||||
gldns_buffer_write(&gbuf,
|
||||
upstream->tsig_dname, upstream->tsig_dname_len); /* Name */
|
||||
gldns_buffer_write_u16(&gbuf, GETDNS_RRTYPE_TSIG); /* Type*/
|
||||
gldns_buffer_write_u16(&gbuf, GETDNS_RRCLASS_ANY); /* Class */
|
||||
gldns_buffer_write_u32(&gbuf, 0); /* TTL */
|
||||
gldns_buffer_write_u16(&gbuf,
|
||||
tsig_info->dname_len + 10 + md_len + 6); /* RdLen */
|
||||
gldns_buffer_write(&gbuf,
|
||||
tsig_info->dname, tsig_info->dname_len); /* Algorithm Name */
|
||||
gldns_buffer_write_u48(&gbuf, time(NULL)); /* Time Signed */
|
||||
gldns_buffer_write_u16(&gbuf, 300); /* Fudge */
|
||||
gldns_buffer_write_u16(&gbuf, md_len); /* MAC Size */
|
||||
gldns_buffer_write(&gbuf, md_buf, md_len); /* MAC*/
|
||||
gldns_buffer_write(&gbuf, req->query, 2); /* Original ID */
|
||||
gldns_buffer_write_u16(&gbuf, 0); /* Error */
|
||||
gldns_buffer_write_u16(&gbuf, 0); /* Other len */
|
||||
|
||||
if (gldns_buffer_position(&gbuf) > gldns_buffer_limit(&gbuf))
|
||||
return req->response - req->query;
|
||||
|
||||
DEBUG_STUB("Sending with TSIG, mac length: %d\n", (int)md_len);
|
||||
gldns_write_uint16(req->query + 10, arcount + 1);
|
||||
req->response = gldns_buffer_current(&gbuf);
|
||||
return req->response - req->query;
|
||||
}
|
||||
|
||||
void
|
||||
_getdns_dns_req_free(getdns_dns_req * req)
|
||||
{
|
||||
|
@ -439,7 +551,7 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
|
|||
+ strlen(name) + 1 + 4 /* dname always smaller then strlen(name) + 1 */
|
||||
+ 12 + opt_options_size /* space needed for OPT (if needed) */
|
||||
+ MAXIMUM_UPSTREAM_OPTION_SPACE
|
||||
/* TODO: TSIG */
|
||||
+ MAXIMUM_TSIG_SPACE
|
||||
+ 7) / 8 * 8;
|
||||
}
|
||||
max_response_sz = (( edns_maximum_udp_payload_size != -1
|
||||
|
|
|
@ -737,7 +737,7 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
|
|||
if (attach_edns_client_subnet_private(netreq))
|
||||
return STUB_OUT_OF_OPTIONS;
|
||||
}
|
||||
pkt_len = netreq->response - netreq->query;
|
||||
pkt_len = _getdns_network_req_add_tsig(netreq);
|
||||
/* We have an initialized packet buffer.
|
||||
* Lets see how much of it we can write
|
||||
*/
|
||||
|
@ -1212,7 +1212,7 @@ stub_tls_write(getdns_upstream *upstream, getdns_tcp_state *tcp,
|
|||
}
|
||||
}
|
||||
|
||||
pkt_len = netreq->response - netreq->query;
|
||||
pkt_len = _getdns_network_req_add_tsig(netreq);
|
||||
/* We have an initialized packet buffer.
|
||||
* Lets see how much of it we can write */
|
||||
|
||||
|
@ -1337,7 +1337,7 @@ stub_udp_write_cb(void *userarg)
|
|||
if (attach_edns_client_subnet_private(netreq))
|
||||
return; /* too many upstream options */
|
||||
}
|
||||
pkt_len = netreq->response - netreq->query;
|
||||
pkt_len = _getdns_network_req_add_tsig(netreq);
|
||||
if ((ssize_t)pkt_len != sendto(netreq->fd, netreq->query, pkt_len, 0,
|
||||
(struct sockaddr *)&netreq->upstream->addr,
|
||||
netreq->upstream->addr_len)) {
|
||||
|
|
|
@ -379,5 +379,8 @@ getdns_return_t _getdns_network_req_add_upstream_option(getdns_network_req * req
|
|||
uint16_t code, uint16_t sz, const void* data);
|
||||
void _getdns_network_req_clear_upstream_options(getdns_network_req * req);
|
||||
|
||||
/* Adds TSIG signature (if needed) and returns query length */
|
||||
size_t _getdns_network_req_add_tsig(getdns_network_req *req);
|
||||
|
||||
#endif
|
||||
/* types-internal.h */
|
||||
|
|
Loading…
Reference in New Issue