options to harden against very small EDNS bufsize or very large query packets.

git-svn-id: file:///svn/unbound/trunk@400 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2007-06-19 14:46:14 +00:00
parent 53d8141a00
commit 890a3fe0a9
7 changed files with 63 additions and 3 deletions

View File

@ -63,6 +63,9 @@
#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)
@ -394,14 +397,20 @@ worker_handle_service_reply(struct comm_point* c, void* arg, int error,
/** 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;
@ -525,7 +534,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
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));
@ -571,6 +580,12 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
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));

View File

@ -128,6 +128,12 @@ server:
# 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

View File

@ -134,6 +134,14 @@ that many targets opportunistically. Enclose the list between quotes ("").
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

View File

@ -100,6 +100,8 @@ config_create()
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);

View File

@ -110,6 +110,11 @@ struct config_file {
/** 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 "". */

View File

@ -128,6 +128,8 @@ infra-cache-numhosts{COLON} { YDOUT; return VAR_INFRA_CACHE_NUMHOSTS;}
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;}

View File

@ -77,6 +77,7 @@ extern struct config_parser_state* cfg_parser;
%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 ;
@ -104,7 +105,8 @@ content_server: server_num_threads | server_verbosity | server_port |
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
{
@ -385,6 +387,26 @@ server_target_fetch_policy: VAR_TARGET_FETCH_POLICY STRING
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));