#include <netdb.h>
#include <signal.h>
+/** Size of an UDP datagram */
+#define NORMAL_UDP_SIZE 512 /* bytes */
+
void
worker_send_cmd(struct worker* worker, ldns_buffer* buffer,
enum worker_commands cmd)
/** check request sanity. Returns error code, 0 OK, or -1 discard.
* @param pkt: the wire packet to examine for sanity.
+ * @param worker: parameters for checking.
*/
static int
-worker_check_request(ldns_buffer* pkt)
+worker_check_request(ldns_buffer* pkt, struct worker* worker)
{
if(ldns_buffer_limit(pkt) < LDNS_HEADER_SIZE) {
verbose(VERB_DETAIL, "request too short, discarded");
return -1;
}
+ if(ldns_buffer_limit(pkt) > NORMAL_UDP_SIZE &&
+ worker->daemon->cfg->harden_large_queries) {
+ verbose(VERB_DETAIL, "request too large, discarded");
+ return -1;
+ }
if(LDNS_QR_WIRE(ldns_buffer_begin(pkt))) {
verbose(VERB_DETAIL, "request has QR bit on, discarded");
return -1;
log_err("handle request called with err=%d", error);
return 0;
}
- if((ret=worker_check_request(c->buffer)) != 0) {
+ if((ret=worker_check_request(c->buffer, worker)) != 0) {
verbose(VERB_ALGO, "worker check request: bad query.");
if(ret != -1) {
LDNS_QR_SET(ldns_buffer_begin(c->buffer));
attach_edns_record(c->buffer, &edns);
return 1;
}
+ if(edns.edns_present && edns.udp_size < NORMAL_UDP_SIZE &&
+ worker->daemon->cfg->harden_short_bufsize) {
+ verbose(VERB_DETAIL, "worker request: EDNS bufsize %d ignored",
+ (int)edns.udp_size);
+ edns.udp_size = NORMAL_UDP_SIZE;
+ }
if(edns.edns_present && edns.udp_size < LDNS_HEADER_SIZE) {
verbose(VERB_ALGO, "worker request: edns is too small.");
LDNS_QR_SET(ldns_buffer_begin(c->buffer));
# positive value: fetch that many targets opportunistically.
# Enclose the list of numbers between quotes ("").
# target-fetch-policy: "3 2 1 0 0"
+
+ # Harden against very small EDNS buffer sizes.
+ # harden_short_bufsize: no
+
+ # Harden against unseemly large queries.
+ # harden_large_queries: no
# Stub zones.
# Create entries like below, to make all queries for 'example.com' and
The default is "3 2 1 0 0". Setting all zeroes, "0 0 0 0 0" gives behaviour
closer to that of BIND 9, while setting "-1 -1 -1 -1 -1" gives behaviour
rumoured to be closer to that of BIND 8.
+.It \fBharden-short-bufsize:\fR <yes or no>
+Very small EDNS buffer sizes from queries are ignored. Default is off, since
+it is legal protocol wise to send these, and unbound tries to give very
+small answers to these queries, where possible.
+.It \fBharden-large-queries:\fR <yes or no>
+Very large queries are ignored. Default is off, since it is legal protocol
+wise to send these, and could be necessary for operation if TSIG or EDNS
+payload is very large.
.El
.Ss Stub Zone Options
cfg->num_ifs = 0;
cfg->ifs = NULL;
cfg->stubs = NULL;
+ cfg->harden_short_bufsize = 0;
+ cfg->harden_large_queries = 0;
return cfg;
error_exit:
config_delete(cfg);
/** the stub definitions, linked list */
struct config_stub* stubs;
+ /** harden against very small edns buffer sizes */
+ int harden_short_bufsize;
+ /** harden against very large query sizes */
+ int harden_large_queries;
+
/** chrootdir, if not "" or chroot will be done */
char* chrootdir;
/** username to change to, if not "". */
infra-cache-numlame{COLON} { YDOUT; return VAR_INFRA_CACHE_NUMLAME;}
num-queries-per-thread{COLON} { YDOUT; return VAR_NUM_QUERIES_PER_THREAD;}
target-fetch-policy{COLON} { YDOUT; return VAR_TARGET_FETCH_POLICY;}
+harden-short-bufsize{COLON} { YDOUT; return VAR_HARDEN_SHORT_BUFSIZE;}
+harden-large-queries{COLON} { YDOUT; return VAR_HARDEN_LARGE_QUERIES;}
stub-zone{COLON} { YDOUT; return VAR_STUB_ZONE;}
name{COLON} { YDOUT; return VAR_NAME;}
stub-addr{COLON} { YDOUT; return VAR_STUB_ADDR;}
%token VAR_INFRA_HOST_TTL VAR_INFRA_LAME_TTL VAR_INFRA_CACHE_SLABS
%token VAR_INFRA_CACHE_NUMHOSTS VAR_INFRA_CACHE_NUMLAME VAR_NAME
%token VAR_STUB_ZONE VAR_STUB_HOST VAR_STUB_ADDR VAR_TARGET_FETCH_POLICY
+%token VAR_HARDEN_SHORT_BUFSIZE VAR_HARDEN_LARGE_QUERIES
%%
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
server_infra_host_ttl | server_infra_lame_ttl |
server_infra_cache_slabs | server_infra_cache_numhosts |
server_infra_cache_numlame | stubstart contents_stub |
- server_target_fetch_policy
+ server_target_fetch_policy | server_harden_short_bufsize |
+ server_harden_large_queries
;
stubstart: VAR_STUB_ZONE
{
cfg_parser->cfg->target_fetch_policy = $2;
}
;
+server_harden_short_bufsize: VAR_HARDEN_SHORT_BUFSIZE STRING
+ {
+ OUTYY(("P(server_harden_short_bufsize:%s)\n", $2));
+ if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
+ yyerror("expected yes or no.");
+ else cfg_parser->cfg->harden_short_bufsize =
+ (strcmp($2, "yes")==0);
+ free($2);
+ }
+ ;
+server_harden_large_queries: VAR_HARDEN_LARGE_QUERIES STRING
+ {
+ OUTYY(("P(server_harden_large_queries:%s)\n", $2));
+ if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
+ yyerror("expected yes or no.");
+ else cfg_parser->cfg->harden_large_queries =
+ (strcmp($2, "yes")==0);
+ free($2);
+ }
+ ;
stub_name: VAR_NAME STRING
{
OUTYY(("P(name:%s)\n", $2));