- Add trustanchor.unbound CH TXT that gets a response with a number

of TXT RRs with a string like "example.com. 2345 1234" with
  the trust anchors and their keytags.


git-svn-id: file:///svn/unbound/trunk@4051 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2017-03-16 09:17:58 +00:00
parent bf1b3c1166
commit 6c456aa15e
13 changed files with 2565 additions and 2265 deletions

View File

@ -69,10 +69,12 @@
#include "iterator/iter_hints.h"
#include "validator/autotrust.h"
#include "validator/val_anchor.h"
#include "validator/val_sigcrypt.h"
#include "respip/respip.h"
#include "libunbound/context.h"
#include "libunbound/libworker.h"
#include "sldns/sbuffer.h"
#include "sldns/wire2str.h"
#include "util/shm_side/shm_main.h"
#ifdef HAVE_SYS_TYPES_H
@ -728,36 +730,41 @@ reply_and_prefetch(struct worker* worker, struct query_info* qinfo,
* Fill CH class answer into buffer. Keeps query.
* @param pkt: buffer
* @param str: string to put into text record (<255).
* array of strings, every string becomes a text record.
* @param num: number of strings in array.
* @param edns: edns reply information.
* @param worker: worker with scratch region.
*/
static void
chaos_replystr(sldns_buffer* pkt, const char* str, struct edns_data* edns,
chaos_replystr(sldns_buffer* pkt, char** str, int num, struct edns_data* edns,
struct worker* worker)
{
size_t len = strlen(str);
int i;
unsigned int rd = LDNS_RD_WIRE(sldns_buffer_begin(pkt));
unsigned int cd = LDNS_CD_WIRE(sldns_buffer_begin(pkt));
if(len>255) len=255; /* cap size of TXT record */
sldns_buffer_clear(pkt);
sldns_buffer_skip(pkt, (ssize_t)sizeof(uint16_t)); /* skip id */
sldns_buffer_write_u16(pkt, (uint16_t)(BIT_QR|BIT_RA));
if(rd) LDNS_RD_SET(sldns_buffer_begin(pkt));
if(cd) LDNS_CD_SET(sldns_buffer_begin(pkt));
sldns_buffer_write_u16(pkt, 1); /* qdcount */
sldns_buffer_write_u16(pkt, 1); /* ancount */
sldns_buffer_write_u16(pkt, (uint16_t)num); /* ancount */
sldns_buffer_write_u16(pkt, 0); /* nscount */
sldns_buffer_write_u16(pkt, 0); /* arcount */
(void)query_dname_len(pkt); /* skip qname */
sldns_buffer_skip(pkt, (ssize_t)sizeof(uint16_t)); /* skip qtype */
sldns_buffer_skip(pkt, (ssize_t)sizeof(uint16_t)); /* skip qclass */
sldns_buffer_write_u16(pkt, 0xc00c); /* compr ptr to query */
sldns_buffer_write_u16(pkt, LDNS_RR_TYPE_TXT);
sldns_buffer_write_u16(pkt, LDNS_RR_CLASS_CH);
sldns_buffer_write_u32(pkt, 0); /* TTL */
sldns_buffer_write_u16(pkt, sizeof(uint8_t) + len);
sldns_buffer_write_u8(pkt, len);
sldns_buffer_write(pkt, str, len);
for(i=0; i<num; i++) {
size_t len = strlen(str[i]);
if(len>255) len=255; /* cap size of TXT record */
sldns_buffer_write_u16(pkt, 0xc00c); /* compr ptr to query */
sldns_buffer_write_u16(pkt, LDNS_RR_TYPE_TXT);
sldns_buffer_write_u16(pkt, LDNS_RR_CLASS_CH);
sldns_buffer_write_u32(pkt, 0); /* TTL */
sldns_buffer_write_u16(pkt, sizeof(uint8_t) + len);
sldns_buffer_write_u8(pkt, len);
sldns_buffer_write(pkt, str[i], len);
}
sldns_buffer_flip(pkt);
edns->edns_version = EDNS_ADVERTISED_VERSION;
edns->udp_size = EDNS_ADVERTISED_SIZE;
@ -768,6 +775,79 @@ chaos_replystr(sldns_buffer* pkt, const char* str, struct edns_data* edns,
attach_edns_record(pkt, edns);
}
/**
* Create CH class trustanchor answer.
* @param pkt: buffer
* @param edns: edns reply information.
* @param worker: worker with scratch region.
*/
static void
chaos_trustanchor(sldns_buffer* pkt, struct edns_data* edns, struct worker* w)
{
int max_txt = 16;
int max_ids = 32;
char* str_array[16];
int num = 0;
struct trust_anchor* ta;
log_info("trustanchor.unbound CH TXT");
if(!w->env.need_to_validate) {
/* no validator module, reply no trustanchors */
chaos_replystr(pkt, NULL, 0, edns, w);
}
/* fill the string with contents */
lock_basic_lock(&w->env.anchors->lock);
RBTREE_FOR(ta, struct trust_anchor*, w->env.anchors->tree) {
int numid = 0;
char* str = (char*)regional_alloc(w->scratchpad, 255);
size_t str_len = 255;
if(!str || num == max_txt) continue;
lock_basic_lock(&ta->lock);
if(ta->numDS == 0 && ta->numDNSKEY == 0) {
/* empty, insecure point */
lock_basic_unlock(&ta->lock);
continue;
}
str_array[num] = str;
num++;
/* spool name of anchor */
(void)sldns_wire2str_dname_buf(ta->name, ta->namelen, str, str_len);
str_len -= strlen(str); str += strlen(str);
/* spool DS */
if(ta->numDS != 0 && ta->ds_rrset) {
struct packed_rrset_data* d=(struct packed_rrset_data*)
ta->ds_rrset->entry.data;
size_t i;
for(i=0; i<d->count; i++) {
uint16_t tag = ds_get_keytag(ta->ds_rrset, i);
if(numid++ > max_ids) continue;
snprintf(str, str_len, " %u", (unsigned)tag);
str_len -= strlen(str); str += strlen(str);
}
}
/* spool DNSKEY */
if(ta->numDNSKEY != 0 && ta->dnskey_rrset) {
struct packed_rrset_data* d=(struct packed_rrset_data*)
ta->dnskey_rrset->entry.data;
size_t i;
for(i=0; i<d->count; i++) {
uint16_t tag = dnskey_calc_keytag(ta->dnskey_rrset, i);
if(numid++ > max_ids) continue;
snprintf(str, str_len, " %u", (unsigned)tag);
str_len -= strlen(str); str += strlen(str);
}
}
log_info("insert string [%d] %s", num, str_array[num-1]);
lock_basic_unlock(&ta->lock);
}
lock_basic_unlock(&w->env.anchors->lock);
chaos_replystr(pkt, str_array, num, edns, w);
regional_free_all(w->scratchpad);
}
/**
* Answer CH class queries.
* @param w: worker
@ -794,13 +874,13 @@ answer_chaos(struct worker* w, struct query_info* qinfo,
char buf[MAXHOSTNAMELEN+1];
if (gethostname(buf, MAXHOSTNAMELEN) == 0) {
buf[MAXHOSTNAMELEN] = 0;
chaos_replystr(pkt, buf, edns, w);
chaos_replystr(pkt, (char**)&buf, 1, edns, w);
} else {
log_err("gethostname: %s", strerror(errno));
chaos_replystr(pkt, "no hostname", edns, w);
chaos_replystr(pkt, (char**)&"no hostname", 1, edns, w);
}
}
else chaos_replystr(pkt, cfg->identity, edns, w);
else chaos_replystr(pkt, &cfg->identity, 1, edns, w);
return 1;
}
if(query_dname_compare(qinfo->qname,
@ -811,10 +891,19 @@ answer_chaos(struct worker* w, struct query_info* qinfo,
if(cfg->hide_version)
return 0;
if(cfg->version==NULL || cfg->version[0]==0)
chaos_replystr(pkt, PACKAGE_STRING, edns, w);
else chaos_replystr(pkt, cfg->version, edns, w);
chaos_replystr(pkt, (char**)&PACKAGE_STRING, 1, edns, w);
else chaos_replystr(pkt, (char**)&cfg->version, 1, edns, w);
return 1;
}
if(query_dname_compare(qinfo->qname,
(uint8_t*)"\013trustanchor\007unbound") == 0)
{
if(cfg->hide_trustanchor)
return 0;
chaos_trustanchor(pkt, edns, w);
return 1;
}
return 0;
}

View File

@ -1,3 +1,9 @@
16 March 2017: Wouter
- Fix that SHM is not inited if not enabled.
- Add trustanchor.unbound CH TXT that gets a response with a number
of TXT RRs with a string like "example.com. 2345 1234" with
the trust anchors and their keytags.
13 March 2017: Wouter
- testbound understands Deckard MATCH rcode question answer commands.
- Fix #1235: Fix too long DNAME expansion produces SERVFAIL instead

View File

@ -316,6 +316,9 @@ server:
# enable to not answer version.server and version.bind queries.
# hide-version: no
# enable to not answer trustanchor.unbound queries.
# hide-trustanchor: no
# the identity to report. Leave "" or default to return hostname.
# identity: ""

View File

@ -596,6 +596,9 @@ If enabled version.server and version.bind queries are refused.
Set the version to report. If set to "", the default, then the package
version is returned.
.TP
.B hide\-trustanchor: \fI<yes or no>
If enabled trustanchor.unbound queries are refused.
.TP
.B target\-fetch\-policy: \fI<"list of numbers">
Set the target fetch policy used by unbound to determine if it should fetch
nameserver target addresses opportunistically. The policy is described per

145
testdata/chaos_trustanchor.rpl vendored Normal file
View File

@ -0,0 +1,145 @@
; config options
; The island of trust is at example.com
server:
trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
hide-trustanchor: no
val-override-date: "20070916134226"
target-fetch-policy: "0 0 0 0 0"
fake-sha1: yes
stub-zone:
name: "."
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
CONFIG_END
SCENARIO_BEGIN Test chaos trustanchor query
; K.ROOT-SERVERS.NET.
RANGE_BEGIN 0 100
ADDRESS 193.0.14.129
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
. IN NS
SECTION ANSWER
. IN NS K.ROOT-SERVERS.NET.
SECTION ADDITIONAL
K.ROOT-SERVERS.NET. IN A 193.0.14.129
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION AUTHORITY
com. IN NS a.gtld-servers.net.
SECTION ADDITIONAL
a.gtld-servers.net. IN A 192.5.6.30
ENTRY_END
RANGE_END
; a.gtld-servers.net.
RANGE_BEGIN 0 100
ADDRESS 192.5.6.30
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
com. IN NS
SECTION ANSWER
com. IN NS a.gtld-servers.net.
SECTION ADDITIONAL
a.gtld-servers.net. IN A 192.5.6.30
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION AUTHORITY
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 1.2.3.4
ENTRY_END
RANGE_END
; ns.example.com.
RANGE_BEGIN 0 100
ADDRESS 1.2.3.4
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
example.com. IN NS
SECTION ANSWER
example.com. IN NS ns.example.com.
example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
SECTION ADDITIONAL
ns.example.com. IN A 1.2.3.4
ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
ENTRY_END
; response to DNSKEY priming query
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
example.com. IN DNSKEY
SECTION ANSWER
example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854}
SECTION AUTHORITY
example.com. IN NS ns.example.com.
example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
SECTION ADDITIONAL
ns.example.com. IN A 1.2.3.4
ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
ENTRY_END
; response to query of interest
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. IN A 10.20.30.40
ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854}
SECTION AUTHORITY
example.com. IN NS ns.example.com.
example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
SECTION ADDITIONAL
ns.example.com. IN A 1.2.3.4
www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
ENTRY_END
RANGE_END
STEP 1 QUERY
ENTRY_BEGIN
REPLY RD DO
SECTION QUESTION
trustanchor.unbound. CH TXT
ENTRY_END
; recursion happens here.
STEP 10 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA DO NOERROR
SECTION QUESTION
trustanchor.unbound. CH TXT
SECTION ANSWER
trustanchor.unbound. CH TXT "example.com. 2854"
ENTRY_END
SCENARIO_END

View File

@ -189,6 +189,7 @@ config_create(void)
cfg->unwanted_threshold = 0;
cfg->hide_identity = 0;
cfg->hide_version = 0;
cfg->hide_trustanchor = 0;
cfg->identity = NULL;
cfg->version = NULL;
cfg->auto_trust_anchor_file_list = NULL;
@ -437,6 +438,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_STR("pidfile:", pidfile)
else S_YNO("hide-identity:", hide_identity)
else S_YNO("hide-version:", hide_version)
else S_YNO("hide-trustanchor:", hide_trustanchor)
else S_STR("identity:", identity)
else S_STR("version:", version)
else S_STRLIST("root-hints:", root_hints)
@ -759,6 +761,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_STR(opt, "pidfile", pidfile)
else O_YNO(opt, "hide-identity", hide_identity)
else O_YNO(opt, "hide-version", hide_version)
else O_YNO(opt, "hide-trustanchor", hide_trustanchor)
else O_STR(opt, "identity", identity)
else O_STR(opt, "version", version)
else O_STR(opt, "target-fetch-policy", target_fetch_policy)

View File

@ -238,6 +238,8 @@ struct config_file {
int hide_identity;
/** do not report version (version.server, version.bind) */
int hide_version;
/** do not report trustanchor (trustanchor.unbound) */
int hide_trustanchor;
/** identity, hostname is returned if "". */
char* identity;
/** version, package version returned if "". */

File diff suppressed because it is too large Load Diff

View File

@ -302,6 +302,7 @@ do-not-query-localhost{COLON} { YDVAR(1, VAR_DO_NOT_QUERY_LOCALHOST) }
access-control{COLON} { YDVAR(2, VAR_ACCESS_CONTROL) }
hide-identity{COLON} { YDVAR(1, VAR_HIDE_IDENTITY) }
hide-version{COLON} { YDVAR(1, VAR_HIDE_VERSION) }
hide-trustanchor{COLON} { YDVAR(1, VAR_HIDE_TRUSTANCHOR) }
identity{COLON} { YDVAR(1, VAR_IDENTITY) }
version{COLON} { YDVAR(1, VAR_VERSION) }
module-config{COLON} { YDVAR(1, VAR_MODULE_CONF) }

File diff suppressed because it is too large Load Diff

View File

@ -235,9 +235,10 @@ extern int yydebug;
VAR_FAKE_DSA = 445,
VAR_FAKE_SHA1 = 446,
VAR_LOG_IDENTITY = 447,
VAR_USE_SYSTEMD = 448,
VAR_SHM_ENABLE = 449,
VAR_SHM_KEY = 450
VAR_HIDE_TRUSTANCHOR = 448,
VAR_USE_SYSTEMD = 449,
VAR_SHM_ENABLE = 450,
VAR_SHM_KEY = 451
};
#endif
/* Tokens. */
@ -431,9 +432,10 @@ extern int yydebug;
#define VAR_FAKE_DSA 445
#define VAR_FAKE_SHA1 446
#define VAR_LOG_IDENTITY 447
#define VAR_USE_SYSTEMD 448
#define VAR_SHM_ENABLE 449
#define VAR_SHM_KEY 450
#define VAR_HIDE_TRUSTANCHOR 448
#define VAR_USE_SYSTEMD 449
#define VAR_SHM_ENABLE 450
#define VAR_SHM_KEY 451
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
@ -444,7 +446,7 @@ union YYSTYPE
char* str;
#line 448 "util/configparser.h" /* yacc.c:1909 */
#line 450 "util/configparser.h" /* yacc.c:1909 */
};
typedef union YYSTYPE YYSTYPE;

View File

@ -137,7 +137,7 @@ extern struct config_parser_state* cfg_parser;
%token VAR_LOCAL_ZONE_OVERRIDE VAR_ACCESS_CONTROL_TAG_ACTION
%token VAR_ACCESS_CONTROL_TAG_DATA VAR_VIEW VAR_ACCESS_CONTROL_VIEW
%token VAR_VIEW_FIRST VAR_SERVE_EXPIRED VAR_FAKE_DSA VAR_FAKE_SHA1
%token VAR_LOG_IDENTITY
%token VAR_LOG_IDENTITY VAR_HIDE_TRUSTANCHOR
%token VAR_USE_SYSTEMD VAR_SHM_ENABLE VAR_SHM_KEY
%%
@ -218,7 +218,8 @@ content_server: server_num_threads | server_verbosity | server_port |
server_qname_minimisation_strict | server_serve_expired |
server_fake_dsa | server_log_identity | server_use_systemd |
server_response_ip_tag | server_response_ip | server_response_ip_data |
server_shm_enable | server_shm_key | server_fake_sha1
server_shm_enable | server_shm_key | server_fake_sha1 |
server_hide_trustanchor
;
stubstart: VAR_STUB_ZONE
{
@ -726,6 +727,15 @@ server_hide_version: VAR_HIDE_VERSION STRING_ARG
free($2);
}
;
server_hide_trustanchor: VAR_HIDE_TRUSTANCHOR STRING_ARG
{
OUTYY(("P(server_hide_trustanchor:%s)\n", $2));
if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
yyerror("expected yes or no.");
else cfg_parser->cfg->hide_trustanchor = (strcmp($2, "yes")==0);
free($2);
}
;
server_identity: VAR_IDENTITY STRING_ARG
{
OUTYY(("P(server_identity:%s)\n", $2));

View File

@ -89,6 +89,8 @@ int shm_main_init(struct daemon* daemon)
/* sanitize */
if(!daemon)
return 0;
if(!daemon->cfg->shm_enable)
return 1;
if(daemon->cfg->stat_interval == 0)
log_warn("shm-enable is yes but statistics-interval is 0");