Merge pull request #119 from dkg/ietf94-privacy-hackathon

Thank you dkg!  Great work!

Interestingly you've put the configuration of those two features at "context" level.  Since both options (just like cookies) relate to upstreams, I think they should be configurable per upstream as well  (perhaps using the context settings as the defaults, over-loadable by those upstream options).  With my cookie implementation, I've implemented activation with an extension, but cookies also relate to upstreams, so perhaps they should be enableable per upstream as well (and have a global over-loadable setting in context).

Cheers,
-- Willem
This commit is contained in:
wtoorop 2015-11-02 16:26:25 +09:00
commit 7230031c0a
10 changed files with 328 additions and 55 deletions

View File

@ -408,6 +408,9 @@ esac
AC_DEFINE_UNQUOTED([EDNS_COOKIE_OPCODE], [10], [The edns cookie option code.])
AC_DEFINE_UNQUOTED([EDNS_COOKIE_ROLLOVER_TIME], [(24 * 60 * 60)], [How often the edns client cookie is refreshed.])
AC_DEFINE_UNQUOTED([MAXIMUM_UPSTREAM_OPTION_SPACE], [3000], [limit for dynamically-generated DNS options])
AC_DEFINE_UNQUOTED([EDNS_PADDING_OPCODE], [65461], [The experimental edns padding option code.])
my_with_libunbound=1
AC_ARG_ENABLE(stub-only, AC_HELP_STRING([--enable-stub-only], [Restricts resolution modes to STUB (which will be the default mode). Removes the libunbound dependency.]))
case "$enable_stub_only" in

View File

@ -881,6 +881,8 @@ getdns_context_create_with_extended_memory_functions(
result->edns_extended_rcode = 0;
result->edns_version = 0;
result->edns_do_bit = 0;
result->edns_client_subnet_private = 0;
result->tls_query_padding_blocksize = 1; /* default is to not try to pad */
result-> tls_ctx = NULL;
result->extension = &result->mini_event.loop;
@ -1897,6 +1899,46 @@ getdns_context_set_edns_do_bit(struct getdns_context *context, uint8_t value)
return GETDNS_RETURN_GOOD;
} /* getdns_context_set_edns_do_bit */
/*
* getdns_context_set_edns_client_subnet_private
*
*/
getdns_return_t
getdns_context_set_edns_client_subnet_private(struct getdns_context *context, uint8_t value)
{
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
/* only allow 1 */
if (value != 0 && value != 1) {
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
}
context->edns_client_subnet_private = value;
dispatch_updated(context, GETDNS_CONTEXT_CODE_EDNS_CLIENT_SUBNET_PRIVATE);
return GETDNS_RETURN_GOOD;
} /* getdns_context_set_edns_client_subnet_private */
/*
* getdns_context_set_tls_query_padding_blocksize
*
*/
getdns_return_t
getdns_context_set_tls_query_padding_blocksize(struct getdns_context *context, uint16_t value)
{
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
/* only allow values between 0 and MAXIMUM_UPSTREAM_OPTION_SPACE - 4
(4 is for the overhead of the option itself) */
if (value > MAXIMUM_UPSTREAM_OPTION_SPACE - 4) {
return GETDNS_RETURN_CONTEXT_UPDATE_FAIL;
}
context->tls_query_padding_blocksize = value;
dispatch_updated(context, GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE);
return GETDNS_RETURN_GOOD;
} /* getdns_context_set_tls_query_padding_blocksize */
/*
* getdns_context_set_extended_memory_functions
*
@ -2200,8 +2242,8 @@ _getdns_context_prepare_for_resolution(struct getdns_context *context,
if(context->tls_ctx == NULL)
return GETDNS_RETURN_BAD_CONTEXT;
/* Be strict and only use the cipher suites recommended in RFC7525
Unless we later fallback to oppotunistic. */
const char* const PREFERRED_CIPHERS = "EECDH+aRSA+AESGCM:EDH+aRSA+AESGCM";
Unless we later fallback to opportunistic. */
const char* const PREFERRED_CIPHERS = "EECDH+aRSA+AESGCM:EECDH+aECDSA+AESGCM:EDH+aRSA+AESGCM";
if (!SSL_CTX_set_cipher_list(context->tls_ctx, PREFERRED_CIPHERS))
return GETDNS_RETURN_BAD_CONTEXT;
if (!SSL_CTX_set_default_verify_paths(context->tls_ctx))
@ -2966,4 +3008,20 @@ getdns_context_get_edns_do_bit(getdns_context *context, uint8_t* value) {
return GETDNS_RETURN_GOOD;
}
getdns_return_t
getdns_context_get_edns_client_subnet_private(getdns_context *context, uint8_t* value) {
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER);
*value = context->edns_client_subnet_private;
return GETDNS_RETURN_GOOD;
}
getdns_return_t
getdns_context_get_tls_query_padding_blocksize(getdns_context *context, uint16_t* value) {
RETURN_IF_NULL(context, GETDNS_RETURN_INVALID_PARAMETER);
RETURN_IF_NULL(value, GETDNS_RETURN_INVALID_PARAMETER);
*value = context->tls_query_padding_blocksize;
return GETDNS_RETURN_GOOD;
}
/* context.c */

View File

@ -157,6 +157,8 @@ struct getdns_context {
uint8_t edns_version;
uint8_t edns_do_bit;
int edns_maximum_udp_payload_size; /* -1 is unset */
uint8_t edns_client_subnet_private;
uint16_t tls_query_padding_blocksize;
SSL_CTX* tls_ctx;
getdns_update_callback update_callback;

View File

@ -194,6 +194,16 @@ getdns_context_get_edns_version(getdns_context *context, uint8_t* value);
getdns_return_t
getdns_context_get_edns_do_bit(getdns_context *context, uint8_t* value);
getdns_return_t
getdns_context_set_edns_client_subnet_private(getdns_context *context, uint8_t value);
getdns_return_t
getdns_context_get_edns_client_subnet_private(getdns_context *context, uint8_t* value);
getdns_return_t
getdns_context_set_tls_query_padding_blocksize(getdns_context *context, uint16_t value);
getdns_return_t
getdns_context_get_tls_query_padding_blocksize(getdns_context *context, uint16_t* value);
/**
* Pretty print the getdns_dict in a given buffer snprintf style.
@ -366,6 +376,10 @@ typedef enum getdns_tls_authentication_t {
#define GETDNS_CONTEXT_CODE_TLS_AUTHENTICATION 618
#define GETDNS_CONTEXT_CODE_TLS_AUTHENTICATION_TEXT "Change related to getdns_context_set_tls_authentication"
#define GETDNS_CONTEXT_CODE_EDNS_CLIENT_SUBNET_PRIVATE 619
#define GETDNS_CONTEXT_CODE_EDNS_CLIENT_SUBNET_PRIVATE_TEXT "Change related to getdns_context_set_edns_client_subnet_private"
#define GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE 620
#define GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE_TEXT "Change related to getdns_context_set_tls_query_padding_blocksize"
getdns_return_t
getdns_context_set_tls_authentication(

View File

@ -13,6 +13,7 @@ getdns_context_get_dnssec_allowed_skew
getdns_context_get_dnssec_trust_anchors
getdns_context_get_dns_transport
getdns_context_get_dns_transport_list
getdns_context_get_edns_client_subnet_private
getdns_context_get_edns_do_bit
getdns_context_get_edns_extended_rcode
getdns_context_get_edns_maximum_udp_payload_size
@ -25,6 +26,7 @@ getdns_context_get_num_pending_requests
getdns_context_get_resolution_type
getdns_context_get_suffix
getdns_context_get_timeout
getdns_context_get_tls_query_padding_blocksize
getdns_context_get_update_callback
getdns_context_get_upstream_recursive_servers
getdns_context_process_async
@ -36,6 +38,7 @@ getdns_context_set_dnssec_allowed_skew
getdns_context_set_dnssec_trust_anchors
getdns_context_set_dns_transport
getdns_context_set_dns_transport_list
getdns_context_set_edns_client_subnet_private
getdns_context_set_edns_do_bit
getdns_context_set_edns_extended_rcode
getdns_context_set_edns_maximum_udp_payload_size
@ -52,6 +55,7 @@ getdns_context_set_return_dnssec_status
getdns_context_set_suffix
getdns_context_set_timeout
getdns_context_set_tls_authentication
getdns_context_set_tls_query_padding_blocksize
getdns_context_set_update_callback
getdns_context_set_upstream_recursive_servers
getdns_context_set_use_threads

View File

@ -113,6 +113,7 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner,
? edns_maximum_udp_payload_size : 1432;
net_req->write_queue_tail = NULL;
net_req->response_len = 0;
net_req->base_query_option_sz = opt_options_size;
net_req->wire_data_sz = wire_data_sz;
if (max_query_sz) {
@ -184,6 +185,75 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner,
return r;
}
/* req->opt + 9 is the length; req->opt + 11 is the start of the
options.
clear_upstream_options() goes back to the per-query options.
*/
void
_getdns_network_req_clear_upstream_options(getdns_network_req * req)
{
size_t pktlen;
if (req->opt) {
gldns_write_uint16(req->opt + 9, req->base_query_option_sz);
req->response = req->opt + 11 + req->base_query_option_sz;
pktlen = req->response - req->query;
gldns_write_uint16(req->query - 2, pktlen);
}
}
/* add_upstream_option appends an option that is derived at send time.
(you can send data as NULL and it will fill with all zeros) */
getdns_return_t
_getdns_network_req_add_upstream_option(getdns_network_req * req, uint16_t code, uint16_t sz, const void* data)
{
uint16_t oldlen;
uint32_t newlen;
uint32_t pktlen;
size_t cur_upstream_option_sz;
/* if no options are set, we can't add upstream options */
if (!req->opt)
return GETDNS_RETURN_GENERIC_ERROR;
/* if TCP, no overflow allowed for length field
https://tools.ietf.org/html/rfc1035#section-4.2.2 */
pktlen = req->response - req->query;
pktlen += 4 + sz;
if (pktlen > UINT16_MAX)
return GETDNS_RETURN_GENERIC_ERROR;
/* no overflow allowed for OPT size either (maybe this is overkill
given the above check?) */
oldlen = gldns_read_uint16(req->opt + 9);
newlen = oldlen + 4 + sz;
if (newlen > UINT16_MAX)
return GETDNS_RETURN_GENERIC_ERROR;
/* avoid overflowing MAXIMUM_UPSTREAM_OPTION_SPACE */
cur_upstream_option_sz = (size_t)oldlen - req->base_query_option_sz;
if (cur_upstream_option_sz + 4 + sz > MAXIMUM_UPSTREAM_OPTION_SPACE)
return GETDNS_RETURN_GENERIC_ERROR;
/* actually add the option: */
gldns_write_uint16(req->opt + 11 + oldlen, code);
gldns_write_uint16(req->opt + 11 + oldlen + 2, sz);
if (data != NULL)
memcpy(req->opt + 11 + oldlen + 4, data, sz);
else
memset(req->opt + 11 + oldlen + 4, 0, sz);
gldns_write_uint16(req->opt + 9, newlen);
/* the response should start right after the options end: */
req->response = req->opt + 11 + newlen;
/* for TCP, adjust the size of the wire format itself: */
gldns_write_uint16(req->query - 2, pktlen);
return GETDNS_RETURN_GOOD;
}
void
_getdns_dns_req_free(getdns_dns_req * req)
{
@ -297,7 +367,8 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
with_opt = edns_do_bit != 0 || edns_maximum_udp_payload_size != 512 ||
edns_extended_rcode != 0 || edns_version != 0 || noptions ||
edns_cookies;
edns_cookies || context->edns_client_subnet_private ||
context->tls_query_padding_blocksize > 1;
edns_maximum_udp_payload_size = with_opt &&
( edns_maximum_udp_payload_size == -1 ||
@ -323,12 +394,7 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
max_query_sz = ( GLDNS_HEADER_SIZE
+ strlen(name) + 1 + 4 /* dname always smaller then strlen(name) + 1 */
+ 12 + opt_options_size /* space needed for OPT (if needed) */
+ ( !edns_cookies ? 0
: 2 /* EDNS0 Option Code */
+ 2 /* Option length = 8 + 16 = 24 */
+ 8 /* client cookie */
+ 16 /* server cookie */
)
+ MAXIMUM_UPSTREAM_OPTION_SPACE
/* TODO: TSIG */
+ 7) / 8 * 8;
}
@ -372,6 +438,8 @@ _getdns_dns_req_new(getdns_context *context, getdns_eventloop *loop,
result->dnssec_return_only_secure = dnssec_return_only_secure;
result->dnssec_return_validation_chain = dnssec_return_validation_chain;
result->edns_cookies = edns_cookies;
result->edns_client_subnet_private = context->edns_client_subnet_private;
result->tls_query_padding_blocksize = context->tls_query_padding_blocksize;
/* will be set by caller */
result->user_pointer = NULL;

View File

@ -46,6 +46,7 @@
#include "util-internal.h"
#include "general.h"
#define STUB_OUT_OF_OPTIONS -5 /* upstream options exceeded MAXIMUM_UPSTREAM_OPTION_SPACE */
#define STUB_TLS_SETUP_ERROR -4
#define STUB_TCP_AGAIN -3
#define STUB_TCP_ERROR -2
@ -129,9 +130,27 @@ calc_new_cookie(getdns_upstream *upstream, uint8_t *cookie)
cookie[i % 8] ^= md_value[i];
}
static uint8_t *
attach_edns_cookie(getdns_upstream *upstream, uint8_t *opt)
static getdns_return_t
attach_edns_client_subnet_private(getdns_network_req *req)
{
/* see
* https://tools.ietf.org/html/draft-ietf-dnsop-edns-client-subnet-04#section-6 */
/* all-zeros is a request to not leak the data further: */
/* "\x00\x00" FAMILY: 0 (because no address) */
/* "\x00" SOURCE PREFIX-LENGTH: 0 */
/* "\x00"; SCOPE PREFIX-LENGTH: 0 */
return _getdns_network_req_add_upstream_option(req,
GLDNS_EDNS_CLIENT_SUBNET,
4, NULL);
}
static getdns_return_t
attach_edns_cookie(getdns_network_req *req)
{
getdns_upstream *upstream = req->upstream;
uint16_t sz;
void* val;
uint8_t buf[8 + 32]; /* server cookies can be no larger than 32 bytes */
rollover_secret();
if (!upstream->has_client_cookie) {
@ -139,12 +158,8 @@ attach_edns_cookie(getdns_upstream *upstream, uint8_t *opt)
upstream->secret = secret;
upstream->has_client_cookie = 1;
gldns_write_uint16(opt + 9, 12); /* rdata len */
gldns_write_uint16(opt + 11, EDNS_COOKIE_OPCODE);
gldns_write_uint16(opt + 13, 8); /* opt len */
memcpy(opt + 15, upstream->client_cookie, 8);
return opt + 23;
sz = 8;
val = upstream->client_cookie;
} else if (upstream->secret != secret) {
memcpy( upstream->prev_client_cookie
, upstream->client_cookie, 8);
@ -152,29 +167,19 @@ attach_edns_cookie(getdns_upstream *upstream, uint8_t *opt)
calc_new_cookie(upstream, upstream->client_cookie);
upstream->secret = secret;
gldns_write_uint16(opt + 9, 12); /* rdata len */
gldns_write_uint16(opt + 11, EDNS_COOKIE_OPCODE);
gldns_write_uint16(opt + 13, 8); /* opt len */
memcpy(opt + 15, upstream->client_cookie, 8);
return opt + 23;
sz = 8;
val = upstream->client_cookie;
} else if (!upstream->has_server_cookie) {
gldns_write_uint16(opt + 9, 12); /* rdata len */
gldns_write_uint16(opt + 11, EDNS_COOKIE_OPCODE);
gldns_write_uint16(opt + 13, 8); /* opt len */
memcpy(opt + 15, upstream->client_cookie, 8);
return opt + 23;
sz = 8;
val = upstream->client_cookie;
} else {
gldns_write_uint16( opt + 9, 12 /* rdata len */
+ upstream->server_cookie_len);
gldns_write_uint16(opt + 11, EDNS_COOKIE_OPCODE);
gldns_write_uint16(opt + 13, 8 /* opt len */
+ upstream->server_cookie_len);
memcpy(opt + 15, upstream->client_cookie, 8);
memcpy(opt + 23, upstream->server_cookie
, upstream->server_cookie_len);
return opt + 23+ upstream->server_cookie_len;
sz = 8 + upstream->server_cookie_len;
memcpy(buf, upstream->client_cookie, 8);
memcpy(buf+8, upstream->server_cookie, upstream->server_cookie_len);
val = buf;
}
return _getdns_network_req_add_upstream_option(req, EDNS_COOKIE_OPCODE, sz, val);
}
static int
@ -681,7 +686,7 @@ static int
stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
{
size_t pkt_len = netreq->response - netreq->query;
size_t pkt_len;
ssize_t written;
uint16_t query_id;
intptr_t query_id_intptr;
@ -704,16 +709,18 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
GLDNS_ID_SET(netreq->query, query_id);
if (netreq->opt) {
_getdns_network_req_clear_upstream_options(netreq);
/* no limits on the max udp payload size with tcp */
gldns_write_uint16(netreq->opt + 3, 65535);
if (netreq->owner->edns_cookies) {
netreq->response = attach_edns_cookie(
netreq->upstream, netreq->opt);
pkt_len = netreq->response - netreq->query;
gldns_write_uint16(netreq->query - 2, pkt_len);
}
if (netreq->owner->edns_cookies)
if (attach_edns_cookie(netreq))
return STUB_OUT_OF_OPTIONS;
if (netreq->owner->edns_client_subnet_private)
if (attach_edns_client_subnet_private(netreq))
return STUB_OUT_OF_OPTIONS;
}
pkt_len = netreq->response - netreq->query;
/* We have an initialized packet buffer.
* Lets see how much of it we can write
*/
@ -908,7 +915,7 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
return NULL;
}
#endif
/* Allow fallback to oppotunisitc if settings permit it*/
/* Allow fallback to opportunistic if settings permit it*/
if (dnsreq->netreqs[0]->tls_auth_min == GETDNS_AUTHENTICATION_HOSTNAME)
SSL_set_verify(ssl, SSL_VERIFY_PEER, tls_verify_callback);
else {
@ -923,6 +930,7 @@ tls_create_object(getdns_dns_req *dnsreq, int fd, getdns_upstream *upstream)
upstream->tls_auth_failed = 1;
return NULL;
} else {
/* no hostname verification, so we will make opportunistic connections */
DEBUG_STUB("--- %s, PROCEEDING WITHOUT HOSTNAME VALIDATION!!\n", __FUNCTION__);
upstream->tls_auth_failed = 1;
SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_callback_with_fallback);
@ -1125,11 +1133,12 @@ static int
stub_tls_write(getdns_upstream *upstream, getdns_tcp_state *tcp,
getdns_network_req *netreq)
{
size_t pkt_len = netreq->response - netreq->query;
size_t pkt_len;
ssize_t written;
uint16_t query_id;
intptr_t query_id_intptr;
SSL* tls_obj = upstream->tls_obj;
uint16_t padding_sz;
int q = tls_connected(upstream);
if (q != 0)
@ -1155,10 +1164,30 @@ stub_tls_write(getdns_upstream *upstream, getdns_tcp_state *tcp,
&netreq->upstream->netreq_by_query_id, &netreq->node));
GLDNS_ID_SET(netreq->query, query_id);
if (netreq->opt)
if (netreq->opt) {
_getdns_network_req_clear_upstream_options(netreq);
/* no limits on the max udp payload size with tcp */
gldns_write_uint16(netreq->opt + 3, 65535);
/* we do not edns_cookie over TLS, since TLS
* provides stronger guarantees than cookies
* already */
if (netreq->owner->edns_client_subnet_private)
if (attach_edns_client_subnet_private(netreq))
return STUB_OUT_OF_OPTIONS;
if (netreq->owner->tls_query_padding_blocksize > 1) {
pkt_len = netreq->response - netreq->query;
pkt_len += 4; /* this accounts for the OPTION-CODE and OPTION-LENGTH of the padding */
padding_sz = pkt_len % netreq->owner->tls_query_padding_blocksize;
if (padding_sz)
padding_sz = netreq->owner->tls_query_padding_blocksize - padding_sz;
if (_getdns_network_req_add_upstream_option(netreq,
EDNS_PADDING_OPCODE,
padding_sz, NULL))
return STUB_OUT_OF_OPTIONS;
}
}
pkt_len = netreq->response - netreq->query;
/* We have an initialized packet buffer.
* Lets see how much of it we can write */
@ -1247,25 +1276,27 @@ stub_udp_write_cb(void *userarg)
DEBUG_STUB("%s\n", __FUNCTION__);
getdns_network_req *netreq = (getdns_network_req *)userarg;
getdns_dns_req *dnsreq = netreq->owner;
size_t pkt_len = netreq->response - netreq->query;
size_t pkt_len;
GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event);
netreq->query_id = arc4random();
GLDNS_ID_SET(netreq->query, netreq->query_id);
if (netreq->opt) {
_getdns_network_req_clear_upstream_options(netreq);
if (netreq->edns_maximum_udp_payload_size == -1)
gldns_write_uint16(netreq->opt + 3,
( netreq->max_udp_payload_size =
netreq->upstream->addr.ss_family == AF_INET6
? 1232 : 1432));
if (netreq->owner->edns_cookies) {
netreq->response = attach_edns_cookie(
netreq->upstream, netreq->opt);
pkt_len = netreq->response - netreq->query;
}
if (netreq->owner->edns_cookies)
if (attach_edns_cookie(netreq))
return; /* too many upstream options */
if (netreq->owner->edns_client_subnet_private)
if (attach_edns_client_subnet_private(netreq))
return; /* too many upstream options */
}
pkt_len = netreq->response - netreq->query;
if ((ssize_t)pkt_len != sendto(netreq->fd, netreq->query, pkt_len, 0,
(struct sockaddr *)&netreq->upstream->addr,
netreq->upstream->addr_len)) {

View File

@ -365,6 +365,54 @@
}
END_TEST
START_TEST (getdns_context_set_context_update_callback_20)
{
/*
* Create a context by calling getdns_context_create()
* Define a callback routine for context changes and call getdns_context_set_context_update_callback() so that it gets called when there are context changes
* Call getdns_context_set_edns_client_subnet_private() setting to 1
* expect: GETDNS_CONTEXT_CODE_EDNS_CLIENT_SUBNET_PRIVATE
*/
struct getdns_context *context = NULL;
CONTEXT_CREATE(TRUE);
ASSERT_RC(getdns_context_set_context_update_callback(context, update_callbackfn),
GETDNS_RETURN_GOOD, "Return code from getdns_context_set_context_update_callback()");
expected_changed_item = GETDNS_CONTEXT_CODE_EDNS_CLIENT_SUBNET_PRIVATE;
ASSERT_RC(getdns_context_set_edns_client_subnet_private(context, 1),
GETDNS_RETURN_GOOD, "Return code from getdns_context_set_edns_client_subnet_private()");
CONTEXT_DESTROY;
}
END_TEST
START_TEST (getdns_context_set_context_update_callback_21)
{
/*
* Create a context by calling getdns_context_create()
* Define a callback routine for context changes and call getdns_context_set_context_update_callback() so that it gets called when there are context changes
* Call getdns_context_set_edns_client_subnet_private() setting to 1
* expect: GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE
*/
struct getdns_context *context = NULL;
CONTEXT_CREATE(TRUE);
ASSERT_RC(getdns_context_set_context_update_callback(context, update_callbackfn),
GETDNS_RETURN_GOOD, "Return code from getdns_context_set_context_update_callback()");
expected_changed_item = GETDNS_CONTEXT_CODE_TLS_QUERY_PADDING_BLOCKSIZE;
ASSERT_RC(getdns_context_set_tls_query_padding_blocksize(context, 1400),
GETDNS_RETURN_GOOD, "Return code from getdns_context_set_tls_query_padding_blocksize()");
CONTEXT_DESTROY;
}
END_TEST
Suite *
@ -391,6 +439,8 @@
tcase_add_test(tc_pos, getdns_context_set_context_update_callback_17);
tcase_add_test(tc_pos, getdns_context_set_context_update_callback_18);
tcase_add_test(tc_pos, getdns_context_set_context_update_callback_19);
tcase_add_test(tc_pos, getdns_context_set_context_update_callback_20);
tcase_add_test(tc_pos, getdns_context_set_context_update_callback_21);
suite_add_tcase(s, tc_pos);
return s;

View File

@ -261,7 +261,7 @@ static char *name;
static getdns_context *context;
static getdns_dict *extensions;
static uint16_t request_type = GETDNS_RRTYPE_NS;
static int timeout, edns0_size;
static int timeout, edns0_size, padding_blocksize;
static int async = 0, interactive = 0;
static enum { GENERAL, ADDRESS, HOSTNAME, SERVICE } calltype = GENERAL;
@ -368,6 +368,7 @@ print_usage(FILE *out, const char *progname)
fprintf(out, "\t-A\taddress lookup (<type> is ignored)\n");
fprintf(out, "\t-B\tBatch mode. Schedule all messages before processing responses.\n");
fprintf(out, "\t-b <bufsize>\tSet edns0 max_udp_payload size\n");
fprintf(out, "\t-c\tSend Client Subnet privacy request\n");
fprintf(out, "\t-D\tSet edns0 do bit\n");
fprintf(out, "\t-d\tclear edns0 do bit\n");
fprintf(out, "\t-e <idle_timeout>\tSet idle timeout in miliseconds\n");
@ -383,6 +384,7 @@ print_usage(FILE *out, const char *progname)
fprintf(out, "\t-n\tSet TLS authentication mode to NONE (default)\n");
fprintf(out, "\t-m\tSet TLS authentication mode to HOSTNAME\n");
fprintf(out, "\t-p\tPretty print response dict\n");
fprintf(out, "\t-P <blocksize>\tPad TLS queries to a multiple of blocksize\n");
fprintf(out, "\t-r\tSet recursing resolution type\n");
fprintf(out, "\t-q\tQuiet mode - don't print response\n");
fprintf(out, "\t-s\tSet stub resolution type (default = recursing)\n");
@ -655,6 +657,10 @@ getdns_return_t parse_args(int argc, char **argv)
getdns_context_set_edns_maximum_udp_payload_size(
context, (uint16_t) edns0_size);
goto next;
case 'c':
if (getdns_context_set_edns_client_subnet_private(context, 1))
return GETDNS_RETURN_GENERIC_ERROR;
break;
case 'D':
(void) getdns_context_set_edns_do_bit(context, 1);
break;
@ -702,6 +708,23 @@ getdns_return_t parse_args(int argc, char **argv)
getdns_context_set_tls_authentication(context,
GETDNS_AUTHENTICATION_HOSTNAME);
break;
case 'P':
if (c[1] != 0 || ++i >= argc || !*argv[i]) {
fprintf(stderr, "tls_query_padding_blocksize "
"expected after -P\n");
return GETDNS_RETURN_GENERIC_ERROR;
}
padding_blocksize = strtol(argv[i], &endptr, 10);
if (*endptr || padding_blocksize < 0) {
fprintf(stderr, "non-negative "
"numeric padding blocksize expected "
"after -P\n");
return GETDNS_RETURN_GENERIC_ERROR;
}
if (getdns_context_set_tls_query_padding_blocksize(
context, padding_blocksize))
return GETDNS_RETURN_GENERIC_ERROR;
goto next;
case 'p':
json = 0;
case 'q':

View File

@ -232,6 +232,19 @@ typedef struct getdns_network_req
*/
uint8_t *query;
uint8_t *opt; /* offset of OPT RR in query */
/* each network_req has a set of base options that are
* specific to the query, which are static and included when
* the network_req is created. When the query is sent out to
* a given upstream, some additional options are added that
* are specific to the upstream. There can be at most
* GETDNS_MAXIMUM_UPSTREAM_OPTION_SPACE bytes of
* upstream-specific options.
* use _getdns_network_req_clear_upstream_options() and
* _getdns_network_req_add_upstream_option() to fiddle with the
*/
size_t base_query_option_sz;
size_t response_len;
uint8_t *response;
size_t wire_data_sz;
@ -262,6 +275,8 @@ typedef struct getdns_dns_req {
int dnssec_return_only_secure;
int dnssec_return_validation_chain;
int edns_cookies;
int edns_client_subnet_private;
uint16_t tls_query_padding_blocksize;
/* Internally used by return_validation_chain */
int dnssec_ok_checking_disabled;
@ -344,5 +359,10 @@ getdns_dns_req *_getdns_dns_req_new(getdns_context *context, getdns_eventloop *l
void _getdns_dns_req_free(getdns_dns_req * req);
/* network request utils */
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);
#endif
/* types-internal.h */