mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
can read bind-style config files for trust anchor information.
git-svn-id: file:///svn/unbound/trunk@569 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
fceea2bcd5
commit
f304a2a459
3 changed files with 167 additions and 25 deletions
|
|
@ -1,3 +1,6 @@
|
||||||
|
31 August 2007: Wouter
|
||||||
|
- can read bind trusted-keys { ... }; files, in a compatibility mode.
|
||||||
|
|
||||||
30 August 2007: Wouter
|
30 August 2007: Wouter
|
||||||
- fixup override date config option.
|
- fixup override date config option.
|
||||||
- config options to control memory usage.
|
- config options to control memory usage.
|
||||||
|
|
|
||||||
|
|
@ -217,6 +217,7 @@ config_delete(struct config_file* cfg)
|
||||||
free(cfg->version);
|
free(cfg->version);
|
||||||
free(cfg->module_conf);
|
free(cfg->module_conf);
|
||||||
config_delstrlist(cfg->trust_anchor_file_list);
|
config_delstrlist(cfg->trust_anchor_file_list);
|
||||||
|
config_delstrlist(cfg->trusted_keys_file_list);
|
||||||
config_delstrlist(cfg->trust_anchor_list);
|
config_delstrlist(cfg->trust_anchor_list);
|
||||||
free(cfg);
|
free(cfg);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -388,18 +388,38 @@ is_bind_special(int c)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Read a keyword skipping bind comments; spaces, specials, restkeywords. */
|
/**
|
||||||
|
* Read a keyword skipping bind comments; spaces, specials, restkeywords.
|
||||||
|
* The file is split into the following tokens:
|
||||||
|
* * special characters, on their own, rdlen=1, { } " ;
|
||||||
|
* * whitespace becomes a single ' ' or tab. Newlines become spaces.
|
||||||
|
* * other words ('keywords')
|
||||||
|
* * comments are skipped if desired
|
||||||
|
* / / C++ style comment to end of line
|
||||||
|
* # to end of line
|
||||||
|
* / * C style comment * /
|
||||||
|
* @param in: file to read from.
|
||||||
|
* @param buf: buffer, what is read is stored after current buffer position.
|
||||||
|
* Space is left in the buffer to write a terminating 0.
|
||||||
|
* @param line: line number is increased per line, for error reports.
|
||||||
|
* @param comments: if 0, comments are not possible and become text.
|
||||||
|
* if 1, comments are skipped entirely.
|
||||||
|
* In BIND files, this is when reading quoted strings, for example
|
||||||
|
* " base 64 text with / / in there "
|
||||||
|
* @return the number of character written to the buffer.
|
||||||
|
* 0 on end of file.
|
||||||
|
*/
|
||||||
static int
|
static int
|
||||||
readkeyword_bindfile(FILE* in, ldns_buffer* buf, int* line)
|
readkeyword_bindfile(FILE* in, ldns_buffer* buf, int* line, int comments)
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
int numdone = 0;
|
int numdone = 0;
|
||||||
while((c = getc(in)) != EOF ) {
|
while((c = getc(in)) != EOF ) {
|
||||||
if(c == '#') { /* # blabla */
|
if(comments && c == '#') { /* # blabla */
|
||||||
skip_to_eol(in);
|
skip_to_eol(in);
|
||||||
(*line)++;
|
(*line)++;
|
||||||
continue;
|
continue;
|
||||||
} else if(c=='/' && numdone>0 && /* /_/ blabla */
|
} else if(comments && c=='/' && numdone>0 && /* /_/ bla*/
|
||||||
ldns_buffer_read_u8_at(buf,
|
ldns_buffer_read_u8_at(buf,
|
||||||
ldns_buffer_position(buf)-1) == '/') {
|
ldns_buffer_position(buf)-1) == '/') {
|
||||||
ldns_buffer_skip(buf, -1);
|
ldns_buffer_skip(buf, -1);
|
||||||
|
|
@ -407,10 +427,11 @@ readkeyword_bindfile(FILE* in, ldns_buffer* buf, int* line)
|
||||||
skip_to_eol(in);
|
skip_to_eol(in);
|
||||||
(*line)++;
|
(*line)++;
|
||||||
continue;
|
continue;
|
||||||
} else if(c=='*' && numdone>0 && /* /_* blabla *_/ */
|
} else if(comments && c=='*' && numdone>0 && /* /_* bla *_/ */
|
||||||
ldns_buffer_read_u8_at(buf,
|
ldns_buffer_read_u8_at(buf,
|
||||||
ldns_buffer_position(buf)-1) == '/') {
|
ldns_buffer_position(buf)-1) == '/') {
|
||||||
ldns_buffer_skip(buf, -1);
|
ldns_buffer_skip(buf, -1);
|
||||||
|
numdone--;
|
||||||
/* skip to end of comment */
|
/* skip to end of comment */
|
||||||
while(c != EOF && (c=getc(in)) != EOF ) {
|
while(c != EOF && (c=getc(in)) != EOF ) {
|
||||||
if(c == '*') {
|
if(c == '*') {
|
||||||
|
|
@ -434,48 +455,157 @@ readkeyword_bindfile(FILE* in, ldns_buffer* buf, int* line)
|
||||||
return numdone;
|
return numdone;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(c == '\n')
|
if(c == '\n') {
|
||||||
|
c = ' ';
|
||||||
(*line)++;
|
(*line)++;
|
||||||
if(ldns_buffer_remaining(buf) < 1) {
|
}
|
||||||
|
/* space for 1 char + 0 string terminator */
|
||||||
|
if(ldns_buffer_remaining(buf) < 2) {
|
||||||
fatal_exit("trusted-keys, %d, string too long", *line);
|
fatal_exit("trusted-keys, %d, string too long", *line);
|
||||||
}
|
}
|
||||||
ldns_buffer_write_u8(buf, c);
|
ldns_buffer_write_u8(buf, c);
|
||||||
numdone++;
|
numdone++;
|
||||||
if(isspace(c))
|
if(isspace(c)) {
|
||||||
|
/* collate whitespace into ' ' */
|
||||||
|
while((c = getc(in)) != EOF ) {
|
||||||
|
if(c == '\n')
|
||||||
|
(*line)++;
|
||||||
|
if(!isspace(c)) {
|
||||||
|
ungetc(c, in);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
return numdone;
|
return numdone;
|
||||||
|
}
|
||||||
if(is_bind_special(c))
|
if(is_bind_special(c))
|
||||||
return numdone;
|
return numdone;
|
||||||
}
|
}
|
||||||
return numdone;
|
return numdone;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** skip through file to { */
|
/** skip through file to { or ; */
|
||||||
static int
|
static int
|
||||||
skip_to_brace_open(FILE* in, int* line)
|
skip_to_special(FILE* in, ldns_buffer* buf, int* line, int spec)
|
||||||
{
|
{
|
||||||
int c;
|
int rdlen;
|
||||||
while((c = getc(in)) != EOF ) {
|
ldns_buffer_clear(buf);
|
||||||
if(c == '\n')
|
while((rdlen=readkeyword_bindfile(in, buf, line, 1))) {
|
||||||
(*line)++;
|
if(rdlen == 1 && isspace(*ldns_buffer_begin(buf))) {
|
||||||
if(isspace(c))
|
ldns_buffer_clear(buf);
|
||||||
continue;
|
continue;
|
||||||
if(c != '{') {
|
}
|
||||||
log_err("trusted-keys, line %d, expected {", *line);
|
if(rdlen != 1 || *ldns_buffer_begin(buf) != spec) {
|
||||||
|
ldns_buffer_write_u8(buf, 0);
|
||||||
|
log_err("trusted-keys, line %d, expected %c got %s",
|
||||||
|
*line, spec, ldns_buffer_begin(buf));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
log_err("trusted-keys, line %d, expected {", *line);
|
log_err("trusted-keys, line %d, expected %c got EOF", *line, spec);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* read contents of trusted-keys{ ... ; clauses and insert keys into storage.
|
||||||
|
* @param anchors: where to store keys
|
||||||
|
* @param buf: buffer to use
|
||||||
|
* @param line: line number in file
|
||||||
|
* @param in: file to read from.
|
||||||
|
* @return 0 on error.
|
||||||
|
*/
|
||||||
static int
|
static int
|
||||||
process_bind_contents(struct val_anchors* anchors, ldns_buffer* buffer,
|
process_bind_contents(struct val_anchors* anchors, ldns_buffer* buf,
|
||||||
int* line)
|
int* line, FILE* in)
|
||||||
{
|
{
|
||||||
|
/* loop over contents, collate strings before ; */
|
||||||
|
/* contents is (numbered): 0 1 2 3 4 5 6 7 8 */
|
||||||
|
/* name. 257 3 5 base64 base64 */
|
||||||
|
/* quoted value: 0 "111" 0 0 0 0 0 0 0 */
|
||||||
|
/* comments value: 1 "000" 1 1 1 "0 0 0 0" 1 */
|
||||||
|
int contnum = 0;
|
||||||
|
int quoted = 0;
|
||||||
|
int comments = 1;
|
||||||
|
int rdlen;
|
||||||
char* str = 0;
|
char* str = 0;
|
||||||
if(!anchor_store_str(anchors, buffer, str)) {
|
ldns_buffer_clear(buf);
|
||||||
|
while((rdlen=readkeyword_bindfile(in, buf, line, comments))) {
|
||||||
|
if(rdlen == 1 && ldns_buffer_position(buf) == 1
|
||||||
|
&& isspace(*ldns_buffer_begin(buf))) {
|
||||||
|
/* starting whitespace is removed */
|
||||||
|
ldns_buffer_clear(buf);
|
||||||
|
continue;
|
||||||
|
} else if(rdlen == 1 && ldns_buffer_current(buf)[-1] == '"') {
|
||||||
|
/* remove " from the string */
|
||||||
|
if(contnum == 0) {
|
||||||
|
quoted = 1;
|
||||||
|
comments = 0;
|
||||||
|
}
|
||||||
|
ldns_buffer_skip(buf, -1);
|
||||||
|
if(contnum > 0 && quoted) {
|
||||||
|
if(ldns_buffer_remaining(buf) < 8+1) {
|
||||||
|
log_err("line %d, too long, %s",
|
||||||
|
*line, ldns_buffer_begin(buf));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ldns_buffer_write(buf, " DNSKEY ", 8);
|
||||||
|
quoted = 0;
|
||||||
|
comments = 1;
|
||||||
|
} else if(contnum > 0)
|
||||||
|
comments = !comments;
|
||||||
|
continue;
|
||||||
|
} else if(rdlen == 1 && ldns_buffer_current(buf)[-1] == ';') {
|
||||||
|
|
||||||
|
if(contnum < 5) {
|
||||||
|
ldns_buffer_write_u8(buf, 0);
|
||||||
|
log_err("line %d, bad key, %s",
|
||||||
|
*line, ldns_buffer_begin(buf));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ldns_buffer_skip(buf, -1);
|
||||||
|
ldns_buffer_write_u8(buf, 0);
|
||||||
|
str = strdup((char*)ldns_buffer_begin(buf));
|
||||||
|
if(!str) {
|
||||||
|
log_err("line %d, allocation failure", *line);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!anchor_store_str(anchors, buf, str)) {
|
||||||
|
log_err("line %d, bad key, %s", *line, str);
|
||||||
|
free(str);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
free(str);
|
||||||
|
ldns_buffer_clear(buf);
|
||||||
|
contnum = 0;
|
||||||
|
quoted = 0;
|
||||||
|
comments = 1;
|
||||||
|
continue;
|
||||||
|
} else if(rdlen == 1 && ldns_buffer_current(buf)[-1] == '}') {
|
||||||
|
if(contnum > 0) {
|
||||||
|
ldns_buffer_write_u8(buf, 0);
|
||||||
|
log_err("line %d, bad key before }, %s",
|
||||||
|
*line, ldns_buffer_begin(buf));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
} else if(rdlen == 1 && isspace(ldns_buffer_current(buf)[-1])) {
|
||||||
|
/* leave whitespace here */
|
||||||
|
} else {
|
||||||
|
/* not space or whatnot, so actual content */
|
||||||
|
contnum ++;
|
||||||
|
if(contnum == 1 && !quoted) {
|
||||||
|
if(ldns_buffer_remaining(buf) < 8+1) {
|
||||||
|
log_err("line %d, too long, %s",
|
||||||
|
*line, ldns_buffer_begin(buf));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ldns_buffer_write(buf, " DNSKEY ", 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log_err("line %d, EOF before }", *line);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -496,27 +626,35 @@ anchor_read_bind_file(struct val_anchors* anchors, ldns_buffer* buffer,
|
||||||
log_err("error opening file %s: %s", fname, strerror(errno));
|
log_err("error opening file %s: %s", fname, strerror(errno));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
fclose(in);
|
verbose(VERB_DETAIL, "reading in bind-compat-mode: '%s'", fname);
|
||||||
/* scan for trusted-keys keyword, ignore everything else */
|
/* scan for trusted-keys keyword, ignore everything else */
|
||||||
ldns_buffer_clear(buffer);
|
ldns_buffer_clear(buffer);
|
||||||
while((rdlen=readkeyword_bindfile(in, buffer, &line_nr)) != 0) {
|
while((rdlen=readkeyword_bindfile(in, buffer, &line_nr, 1)) != 0) {
|
||||||
if(rdlen != 12 || strncmp((char*)ldns_buffer_begin(buffer),
|
if(rdlen != 12 || strncmp((char*)ldns_buffer_begin(buffer),
|
||||||
"trusted-keys", 12) != 0) {
|
"trusted-keys", 12) != 0) {
|
||||||
ldns_buffer_clear(buffer);
|
ldns_buffer_clear(buffer);
|
||||||
/* ignore everything but trusted-keys */
|
/* ignore everything but trusted-keys */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(!skip_to_brace_open(in, &line_nr)) {
|
if(!skip_to_special(in, buffer, &line_nr, '{')) {
|
||||||
log_err("error in trusted key: \"%s\"", fname);
|
log_err("error in trusted key: \"%s\"", fname);
|
||||||
|
fclose(in);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* process contents */
|
/* process contents */
|
||||||
if(!process_bind_contents(anchors, buffer, &line_nr)) {
|
if(!process_bind_contents(anchors, buffer, &line_nr, in)) {
|
||||||
log_err("error in trusted key: \"%s\"", fname);
|
log_err("error in trusted key: \"%s\"", fname);
|
||||||
|
fclose(in);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(!skip_to_special(in, buffer, &line_nr, ';')) {
|
||||||
|
log_err("error in trusted key: \"%s\"", fname);
|
||||||
|
fclose(in);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
ldns_buffer_clear(buffer);
|
ldns_buffer_clear(buffer);
|
||||||
}
|
}
|
||||||
|
fclose(in);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue