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:
Wouter Wijngaards 2007-08-31 07:44:16 +00:00
parent fceea2bcd5
commit f304a2a459
3 changed files with 167 additions and 25 deletions

View file

@ -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.

View file

@ -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);
} }

View file

@ -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;
} }