Fix out-of-order XML element parse, zone name check and newline filter for unbound-anchor XML parse.

git-svn-id: file:///svn/unbound/trunk@2274 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
Wouter Wijngaards 2010-10-01 15:01:49 +00:00
parent cb978ff7be
commit 236d4cea25
2 changed files with 137 additions and 24 deletions

View file

@ -1129,14 +1129,41 @@ struct xml_data {
char* tag;
/** current date to use during the parse */
time_t date;
/** do we want to use this anchor? */
int use_key;
/** number of keys usefully read in */
int num_keys;
/** the compiled anchors as DS records */
BIO* ds;
/** do we want to use this anchor? */
int use_key;
/** the current anchor: Zone */
BIO* czone;
/** the current anchor: KeyTag */
BIO* ctag;
/** the current anchor: Algorithm */
BIO* calgo;
/** the current anchor: DigestType */
BIO* cdigtype;
/** the current anchor: Digest*/
BIO* cdigest;
};
/** The BIO for the tag */
static BIO*
xml_selectbio(struct xml_data* data, const char* tag)
{
BIO* b = NULL;
if(strcasecmp(tag, "KeyTag") == 0)
b = data->ctag;
else if(strcasecmp(tag, "Algorithm") == 0)
b = data->calgo;
else if(strcasecmp(tag, "DigestType") == 0)
b = data->cdigtype;
else if(strcasecmp(tag, "Digest") == 0)
b = data->cdigest;
return b;
}
/**
* XML handle character data, the data inside an element.
* @param userData: xml_data structure
@ -1148,6 +1175,7 @@ void
xml_charhandle(void *userData, const XML_Char *s, int len)
{
struct xml_data* data = (struct xml_data*)userData;
BIO* b = NULL;
/* skip characters outside of elements */
if(!data->tag)
return;
@ -1160,14 +1188,19 @@ xml_charhandle(void *userData, const XML_Char *s, int len)
printf("%c", s[i]);
printf("'\n");
}
if(strcasecmp(data->tag, "Zone") == 0) {
if(BIO_write(data->czone, s, len) <= 0) {
if(verb) printf("out of memory in BIO_write\n");
exit(0);
}
return;
}
/* only store if key is used */
if(!data->use_key)
return;
if(strcasecmp(data->tag, "KeyTag") == 0 ||
strcasecmp(data->tag, "Algorithm") == 0 ||
strcasecmp(data->tag, "DigestType") == 0 ||
strcasecmp(data->tag, "Digest") == 0) {
if(BIO_write(data->ds, s, len) <= 0) {
b = xml_selectbio(data, data->tag);
if(b) {
if(BIO_write(b, s, len) <= 0) {
if(verb) printf("out of memory in BIO_write\n");
exit(0);
}
@ -1266,7 +1299,6 @@ xml_convertdate(const char* str)
static void
handle_keydigest(struct xml_data* data, const XML_Char **atts)
{
const char* s = ". IN DS";
data->use_key = 0;
if(find_att(atts, "validFrom")) {
time_t from = xml_convertdate(find_att(atts, "validFrom"));
@ -1288,11 +1320,26 @@ handle_keydigest(struct xml_data* data, const XML_Char **atts)
}
/* yes we want to use this key */
data->use_key = 1;
data->num_keys++;
if(BIO_write(data->ds, s, (int)strlen(s)) <= 0) {
if(verb) printf("out of memory in BIO_write\n");
exit(0);
}
BIO_reset(data->ctag);
BIO_reset(data->calgo);
BIO_reset(data->cdigtype);
BIO_reset(data->cdigest);
}
/** See if XML element equals the zone name */
static int
xml_is_zone_name(BIO* zone, char* name)
{
char buf[1024];
char* z = NULL;
long zlen;
BIO_seek(zone, 0);
zlen = BIO_get_mem_data(zone, &z);
if(!zlen || !z) return 0;
if(zlen >= (long)sizeof(buf)) return 0;
memmove(buf, z, (size_t)zlen);
buf[zlen] = 0;
return (strncasecmp(buf, name, strlen(name)) == 0);
}
/**
@ -1307,6 +1354,7 @@ static void
xml_startelem(void *userData, const XML_Char *name, const XML_Char **atts)
{
struct xml_data* data = (struct xml_data*)userData;
BIO* b;
if(verb>=4) printf("xml tag start '%s'\n", name);
free(data->tag);
data->tag = strdup(name);
@ -1323,22 +1371,73 @@ xml_startelem(void *userData, const XML_Char *name, const XML_Char **atts)
/* handle attributes to particular types */
if(strcasecmp(name, "KeyDigest") == 0) {
handle_keydigest(data, atts);
return;
} else if(strcasecmp(name, "Zone") == 0) {
BIO_reset(data->czone);
return;
}
/* write whitespace separators to outputBIO here */
if(!data->use_key)
return;
if(strcasecmp(data->tag, "KeyTag") == 0 ||
strcasecmp(data->tag, "Algorithm") == 0 ||
strcasecmp(data->tag, "DigestType") == 0 ||
strcasecmp(data->tag, "Digest") == 0) {
if(BIO_write(data->ds, " ", 1) <= 0) {
if(verb) printf("out of memory in BIO_write\n");
exit(0);
}
b = xml_selectbio(data, data->tag);
if(b) {
/* empty it */
BIO_reset(b);
}
}
/** Append str to bio */
static void
xml_append_str(BIO* b, const char* s)
{
if(BIO_write(b, s, (int)strlen(s)) <= 0) {
if(verb) printf("out of memory in BIO_write\n");
exit(0);
}
}
/** Append bio to bio */
static void
xml_append_bio(BIO* b, BIO* a)
{
char* z = NULL;
long i, len;
BIO_seek(a, 0);
len = BIO_get_mem_data(a, &z);
if(!len || !z) {
if(verb) printf("out of memory in BIO_write\n");
exit(0);
}
/* remove newlines in the data here */
for(i=0; i<len; i++) {
if(z[i] == '\r' || z[i] == '\n')
z[i] = ' ';
}
/* write to BIO */
if(BIO_write(b, z, len) <= 0) {
if(verb) printf("out of memory in BIO_write\n");
exit(0);
}
}
/** write the parsed xml-DS to the DS list */
static void
xml_append_ds(struct xml_data* data)
{
/* write DS to accumulated DS */
xml_append_str(data->ds, ". IN DS ");
xml_append_bio(data->ds, data->ctag);
xml_append_str(data->ds, " ");
xml_append_bio(data->ds, data->calgo);
xml_append_str(data->ds, " ");
xml_append_bio(data->ds, data->cdigtype);
xml_append_str(data->ds, " ");
xml_append_bio(data->ds, data->cdigest);
xml_append_str(data->ds, "\n");
data->num_keys++;
}
/**
* XML end of element. This callback is called whenever an XML tag ends.
* XML_Char is UTF8.
@ -1353,9 +1452,12 @@ xml_endelem(void *userData, const XML_Char *name)
free(data->tag);
data->tag = NULL;
if(strcasecmp(name, "KeyDigest") == 0) {
if(data->use_key)
xml_append_ds(data);
data->use_key = 0;
if(BIO_write(data->ds, "\n", 1) <= 0) {
if(verb) printf("out of memory in BIO_write\n");
} else if(strcasecmp(name, "Zone") == 0) {
if(!xml_is_zone_name(data->czone, ".")) {
if(verb) printf("xml not for the right zone\n");
exit(0);
}
}
@ -1373,7 +1475,13 @@ xml_parse_setup(XML_Parser parser, struct xml_data* data, time_t now)
data->parser = parser;
data->date = now;
data->ds = BIO_new(BIO_s_mem());
if(!data->ds) {
data->ctag = BIO_new(BIO_s_mem());
data->czone = BIO_new(BIO_s_mem());
data->calgo = BIO_new(BIO_s_mem());
data->cdigtype = BIO_new(BIO_s_mem());
data->cdigest = BIO_new(BIO_s_mem());
if(!data->ds || !data->ctag || !data->calgo || !data->czone ||
!data->cdigtype || !data->cdigest) {
if(verb) printf("out of memory\n");
exit(0);
}
@ -1444,6 +1552,11 @@ xml_parse(BIO* xml, time_t now)
(void)fwrite(pp, (size_t)len, 1, stdout);
printf("'\n");
}
BIO_free(data.czone);
BIO_free(data.ctag);
BIO_free(data.calgo);
BIO_free(data.cdigtype);
BIO_free(data.cdigest);
if(data.num_keys == 0) {
/* the root zone seems to have gone insecure */

Binary file not shown.