diff --git a/a.c b/a.c index 59701fa..62aa3b3 100644 --- a/a.c +++ b/a.c @@ -20,44 +20,44 @@ static struct rr *a_parse(char *name, long ttl, int type, char *s) { - struct rr_a *rr = getmem(sizeof(*rr)); + struct rr_a *rr = getmem(sizeof(*rr)); - if (extract_ipv4(&s, "IPv4 address", &rr->address) <= 0) - return NULL; - if (*s) { - return bitch("garbage after valid A data"); - } + if (extract_ipv4(&s, "IPv4 address", &rr->address) <= 0) + return NULL; + if (*s) { + return bitch("garbage after valid A data"); + } - return store_record(type, name, ttl, rr); + return store_record(type, name, ttl, rr); } static char* a_human(struct rr *rrv) { - RRCAST(a); - char s[1024]; + RRCAST(a); + char s[1024]; - if (inet_ntop(AF_INET, &rr->address, s, 1024)) - return quickstrdup_temp(s); - return "????"; + if (inet_ntop(AF_INET, &rr->address, s, 1024)) + return quickstrdup_temp(s); + return "????"; } static struct binary_data a_wirerdata(struct rr *rrv) { - RRCAST(a); - struct binary_data r; + RRCAST(a); + struct binary_data r; - r.length = sizeof(rr->address); - r.data = (void *)&rr->address; - return r; + r.length = sizeof(rr->address); + r.data = (void *)&rr->address; + return r; } static void* a_validate_set(struct rr_set *rr_set) { - if (rr_set->named_rr->flags & NAME_FLAG_CONTAINS_SLASH) { - struct rr *rr = rr_set->tail; - return moan(rr->file_name, rr->line, "host name contains '/'"); - } - return NULL; + if (rr_set->named_rr->flags & NAME_FLAG_CONTAINS_SLASH) { + struct rr *rr = rr_set->tail; + return moan(rr->file_name, rr->line, "host name contains '/'"); + } + return NULL; } struct rr_methods a_methods = { a_parse, a_human, a_wirerdata, a_validate_set, NULL }; diff --git a/aaaa.c b/aaaa.c index 863c521..7bdc469 100644 --- a/aaaa.c +++ b/aaaa.c @@ -20,44 +20,44 @@ static struct rr *aaaa_parse(char *name, long ttl, int type, char *s) { - struct rr_aaaa *rr = getmem(sizeof(*rr)); + struct rr_aaaa *rr = getmem(sizeof(*rr)); - if (extract_ipv6(&s, "IPv6 address", &rr->address) <= 0) - return NULL; - if (*s) { - return bitch("garbage after valid AAAA data"); - } + if (extract_ipv6(&s, "IPv6 address", &rr->address) <= 0) + return NULL; + if (*s) { + return bitch("garbage after valid AAAA data"); + } - return store_record(type, name, ttl, rr); + return store_record(type, name, ttl, rr); } static char* aaaa_human(struct rr *rrv) { - RRCAST(aaaa); + RRCAST(aaaa); char s[1024]; - if (inet_ntop(AF_INET6, &rr->address, s, 1024)) - return quickstrdup_temp(s); - return "????"; + if (inet_ntop(AF_INET6, &rr->address, s, 1024)) + return quickstrdup_temp(s); + return "????"; } static struct binary_data aaaa_wirerdata(struct rr *rrv) { - RRCAST(aaaa); - struct binary_data r; + RRCAST(aaaa); + struct binary_data r; - r.length = sizeof(rr->address); - r.data = (void *)&rr->address; - return r; + r.length = sizeof(rr->address); + r.data = (void *)&rr->address; + return r; } static void* aaaa_validate_set(struct rr_set *rr_set) { - if (rr_set->named_rr->flags & NAME_FLAG_CONTAINS_SLASH) { - struct rr *rr = rr_set->tail; - return moan(rr->file_name, rr->line, "host name contains '/'"); - } - return NULL; + if (rr_set->named_rr->flags & NAME_FLAG_CONTAINS_SLASH) { + struct rr *rr = rr_set->tail; + return moan(rr->file_name, rr->line, "host name contains '/'"); + } + return NULL; } struct rr_methods aaaa_methods = { aaaa_parse, aaaa_human, aaaa_wirerdata, aaaa_validate_set, NULL }; diff --git a/afsdb.c b/afsdb.c index 877d149..6cdefb3 100644 --- a/afsdb.c +++ b/afsdb.c @@ -19,42 +19,42 @@ static struct rr *afsdb_parse(char *name, long ttl, int type, char *s) { - struct rr_afsdb *rr = getmem(sizeof(*rr)); + struct rr_afsdb *rr = getmem(sizeof(*rr)); - rr->subtype = extract_integer(&s, "AFSDB subtype", NULL); - if (rr->subtype < 0) - return NULL; + rr->subtype = extract_integer(&s, "AFSDB subtype", NULL); + if (rr->subtype < 0) + return NULL; - if (rr->subtype != 1 && rr->subtype != 2) - return bitch("unknown AFSDB subtype"); + if (rr->subtype != 1 && rr->subtype != 2) + return bitch("unknown AFSDB subtype"); - rr->hostname = extract_name(&s, "AFSDB hostname", 0); - if (!rr->hostname) - return NULL; + rr->hostname = extract_name(&s, "AFSDB hostname", 0); + if (!rr->hostname) + return NULL; - if (*s) { - return bitch("garbage after valid AFSDB data"); - } + if (*s) { + return bitch("garbage after valid AFSDB data"); + } - return store_record(type, name, ttl, rr); + return store_record(type, name, ttl, rr); } static char* afsdb_human(struct rr *rrv) { - RRCAST(afsdb); + RRCAST(afsdb); char s[1024]; snprintf(s, 1024, "%d %s", - rr->subtype, rr->hostname); + rr->subtype, rr->hostname); return quickstrdup_temp(s); } static struct binary_data afsdb_wirerdata(struct rr *rrv) { - RRCAST(afsdb); + RRCAST(afsdb); return compose_binary_data("2d", 1, - rr->subtype, name2wire_name(rr->hostname)); + rr->subtype, name2wire_name(rr->hostname)); } struct rr_methods afsdb_methods = { afsdb_parse, afsdb_human, afsdb_wirerdata, NULL, NULL }; diff --git a/base32hex.c b/base32hex.c index 0d9216b..16b218c 100644 --- a/base32hex.c +++ b/base32hex.c @@ -36,319 +36,319 @@ int decode_base32hex(void *dest, char *src, size_t dstsize) { - size_t processed = 0; - int full_bytes = 0; - unsigned char *dst = dest; + size_t processed = 0; + int full_bytes = 0; + unsigned char *dst = dest; - while (*src) { - int v; - if (*src >= 'A' && *src <= 'V') - v = *src - 'A' + 10; - else if (*src >= 'a' && *src <= 'v') - v = *src - 'a' + 10; - else if (*src >= '0' && *src <= '9') - v = *src - '0'; - else if (isspace(*src) || *src == '=') { - src++; - continue; - } else { - /* any junk chars means input is corrupted */ - errno = EINVAL; - return -1; - } - src++; - if (processed % 8 == 0) { - if (dstsize <= 0) { - errno = EINVAL; - return -1; - } - dst[0] &= 0x07; - dst[0] |= (v << 3) & 0xF8; - processed++; - } else if (processed % 8 == 1) { - if (dstsize < 1) { - errno = EINVAL; - return -1; - } - dst[0] &= 0xF8; - dst[0] |= (v >> 2) & 0x07; - if (dstsize >= 2) { - dst[1] &= 0x3F; - dst[1] |= (v << 6) & 0xC0; - } - processed++; - full_bytes++; - } else if (processed % 8 == 2) { - if (dstsize < 2) { - errno = EINVAL; - return -1; - } - dst[1] &= 0xC1; - dst[1] |= (v << 1) & 0x3E; - processed++; - } else if (processed % 8 == 3) { - if (dstsize < 2) { - errno = EINVAL; - return -1; - } - dst[1] &= 0xFE; - dst[1] |= (v >> 4) & 0x01; - if (dstsize >= 3) { - dst[2] &= 0x0F; - dst[2] |= (v << 4) & 0xF0; - } - processed++; - full_bytes++; - } else if (processed % 8 == 4) { - if (dstsize < 3) { - errno = EINVAL; - return -1; - } - dst[2] &= 0xF0; - dst[2] |= (v >> 1) & 0x0F; - if (dstsize >= 4) { - dst[3] &= 0x7F; - dst[3] |= (v << 7) & 0x80; - } - processed++; - full_bytes++; - } else if (processed % 8 == 5) { - if (dstsize < 4) { - errno = EINVAL; - return -1; - } - dst[3] &= 0x83; - dst[3] |= (v << 2) & 0x7C; - processed++; - } else if (processed % 8 == 6) { - if (dstsize < 4) { - errno = EINVAL; - return -1; - } - dst[3] &= 0xFC; - dst[3] |= (v >> 3) & 0x03; - if (dstsize >= 5) { - dst[4] &= 0x1F; - dst[4] |= (v << 5) & 0xE0; - } - processed++; - full_bytes++; - } else { - if (dstsize < 5) { - errno = EINVAL; - return -1; - } - dst[4] &= 0xE0; - dst[4] |= v & 0x1F; - processed++; - dst += 5; - dstsize -= 5; - full_bytes++; - } - } - return full_bytes; + while (*src) { + int v; + if (*src >= 'A' && *src <= 'V') + v = *src - 'A' + 10; + else if (*src >= 'a' && *src <= 'v') + v = *src - 'a' + 10; + else if (*src >= '0' && *src <= '9') + v = *src - '0'; + else if (isspace(*src) || *src == '=') { + src++; + continue; + } else { + /* any junk chars means input is corrupted */ + errno = EINVAL; + return -1; + } + src++; + if (processed % 8 == 0) { + if (dstsize <= 0) { + errno = EINVAL; + return -1; + } + dst[0] &= 0x07; + dst[0] |= (v << 3) & 0xF8; + processed++; + } else if (processed % 8 == 1) { + if (dstsize < 1) { + errno = EINVAL; + return -1; + } + dst[0] &= 0xF8; + dst[0] |= (v >> 2) & 0x07; + if (dstsize >= 2) { + dst[1] &= 0x3F; + dst[1] |= (v << 6) & 0xC0; + } + processed++; + full_bytes++; + } else if (processed % 8 == 2) { + if (dstsize < 2) { + errno = EINVAL; + return -1; + } + dst[1] &= 0xC1; + dst[1] |= (v << 1) & 0x3E; + processed++; + } else if (processed % 8 == 3) { + if (dstsize < 2) { + errno = EINVAL; + return -1; + } + dst[1] &= 0xFE; + dst[1] |= (v >> 4) & 0x01; + if (dstsize >= 3) { + dst[2] &= 0x0F; + dst[2] |= (v << 4) & 0xF0; + } + processed++; + full_bytes++; + } else if (processed % 8 == 4) { + if (dstsize < 3) { + errno = EINVAL; + return -1; + } + dst[2] &= 0xF0; + dst[2] |= (v >> 1) & 0x0F; + if (dstsize >= 4) { + dst[3] &= 0x7F; + dst[3] |= (v << 7) & 0x80; + } + processed++; + full_bytes++; + } else if (processed % 8 == 5) { + if (dstsize < 4) { + errno = EINVAL; + return -1; + } + dst[3] &= 0x83; + dst[3] |= (v << 2) & 0x7C; + processed++; + } else if (processed % 8 == 6) { + if (dstsize < 4) { + errno = EINVAL; + return -1; + } + dst[3] &= 0xFC; + dst[3] |= (v >> 3) & 0x03; + if (dstsize >= 5) { + dst[4] &= 0x1F; + dst[4] |= (v << 5) & 0xE0; + } + processed++; + full_bytes++; + } else { + if (dstsize < 5) { + errno = EINVAL; + return -1; + } + dst[4] &= 0xE0; + dst[4] |= v & 0x1F; + processed++; + dst += 5; + dstsize -= 5; + full_bytes++; + } + } + return full_bytes; } int encode_base32hex(void *dest, size_t dstsize, void *source, size_t srclength) { - size_t need_dstsize; - int byte = 0; - unsigned char *dst = dest; - unsigned char *src = source; - int i; + size_t need_dstsize; + int byte = 0; + unsigned char *dst = dest; + unsigned char *src = source; + int i; - need_dstsize = 8*(srclength / 5); - switch (srclength % 5) { - case 1: need_dstsize += 2; break; - case 2: need_dstsize += 4; break; - case 3: need_dstsize += 5; break; - case 4: need_dstsize += 7; break; - } - if (dstsize < need_dstsize) { - errno = EINVAL; - return -1; - } - while (srclength) { - switch (byte) { - case 0: - dst[0] = *src >> 3; - dst[1] = (*src & 0x07) << 2; - break; - case 1: - dst[1] |= (*src >> 6) & 0x03; - dst[2] = (*src >> 1) & 0x1f; - dst[3] = (*src & 0x01) << 4; - break; - case 2: - dst[3] |= (*src >> 4) & 0x0f; - dst[4] = (*src & 0x0f) << 1; - break; - case 3: - dst[4] |= (*src >> 7) & 0x01; - dst[5] = (*src >> 2) & 0x1f; - dst[6] = (*src & 0x03) << 3; - break; - case 4: - dst[6] |= (*src >> 5) & 0x07; - dst[7] = *src & 0x1f; - break; - } + need_dstsize = 8*(srclength / 5); + switch (srclength % 5) { + case 1: need_dstsize += 2; break; + case 2: need_dstsize += 4; break; + case 3: need_dstsize += 5; break; + case 4: need_dstsize += 7; break; + } + if (dstsize < need_dstsize) { + errno = EINVAL; + return -1; + } + while (srclength) { + switch (byte) { + case 0: + dst[0] = *src >> 3; + dst[1] = (*src & 0x07) << 2; + break; + case 1: + dst[1] |= (*src >> 6) & 0x03; + dst[2] = (*src >> 1) & 0x1f; + dst[3] = (*src & 0x01) << 4; + break; + case 2: + dst[3] |= (*src >> 4) & 0x0f; + dst[4] = (*src & 0x0f) << 1; + break; + case 3: + dst[4] |= (*src >> 7) & 0x01; + dst[5] = (*src >> 2) & 0x1f; + dst[6] = (*src & 0x03) << 3; + break; + case 4: + dst[6] |= (*src >> 5) & 0x07; + dst[7] = *src & 0x1f; + break; + } - srclength--; - src++; - byte++; - if (byte == 5) { - dst += 8; - byte = 0; - } - } - dst = dest; - for (i = 0; i < need_dstsize; i++) { - if (*dst < 10) - *dst = *dst +'0'; - else if (*dst < 32) - *dst = *dst - 10 + 'a'; - else - *dst = '?'; - dst++; - } - return need_dstsize; + srclength--; + src++; + byte++; + if (byte == 5) { + dst += 8; + byte = 0; + } + } + dst = dest; + for (i = 0; i < need_dstsize; i++) { + if (*dst < 10) + *dst = *dst +'0'; + else if (*dst < 32) + *dst = *dst - 10 + 'a'; + else + *dst = '?'; + dst++; + } + return need_dstsize; } #ifdef TEST_PROGRAM static int ok_string_test(int testnum, char *src, char *expect) { - unsigned char dstbuf[512]; - unsigned char reverse_buf[1024]; - int r, r0, i; - int expect_sz = strlen(expect); - int expect_reverse; - char *s, *d; + unsigned char dstbuf[512]; + unsigned char reverse_buf[1024]; + int r, r0, i; + int expect_sz = strlen(expect); + int expect_reverse; + char *s, *d; - if (expect_sz >= 512) { - printf("test %d: NOT OK: internal *test* error, buffer too small for proper testing, FIXME\n", testnum); - return 1; - } - memset(dstbuf, 0xAA, 512); - r = decode_base32hex(dstbuf, src, expect_sz); - if (r != expect_sz) { - printf("test %d: NOT OK: expect size %d, got %d\n", testnum, expect_sz, r); - return 1; - } else if (memcmp(dstbuf, expect, r) != 0) { - printf("test %d: NOT OK: unexpected buffer content\n", testnum); - return 1; - } - if (dstbuf[expect_sz] != 0xAA) { - printf("test %d: NOT OK: corrupts memory with \"just enough\" bufsize\n", testnum); - return 1; - } - r = encode_base32hex(reverse_buf, 1024, dstbuf, expect_sz); - s = src; d = (char*)dstbuf; - expect_reverse = 0; - while (*s) { - if (*s != ' ' && *s != '=') { - *d++ = tolower(*s); - expect_reverse++; - } - s++; - } - if (r != expect_reverse) { - printf("test %d: NOT OK: REVERSE: expect size %d, got %d\n", testnum, expect_reverse, r); - return 1; - } else if (memcmp(reverse_buf, dstbuf, r) != 0) { - printf("test %d: NOT OK: REVERSE: unexpected buffer content\n", testnum); - return 1; - } - memset(dstbuf, 0xAA, 512); - for (i = 0; i < expect_sz; i++) { - r0 = decode_base32hex(dstbuf, src, i); - if (r0 > 0) { - printf("test %d: NOT OK: buffer size %d should not be enough\n", testnum, i); - return 1; - } - if (dstbuf[i] != 0xAA) { - printf("test %d: NOT OK: corrupts memory with bufsize %d\n", testnum, i); - return 1; - } - } - printf("test %d: ok\n", testnum); - return 0; + if (expect_sz >= 512) { + printf("test %d: NOT OK: internal *test* error, buffer too small for proper testing, FIXME\n", testnum); + return 1; + } + memset(dstbuf, 0xAA, 512); + r = decode_base32hex(dstbuf, src, expect_sz); + if (r != expect_sz) { + printf("test %d: NOT OK: expect size %d, got %d\n", testnum, expect_sz, r); + return 1; + } else if (memcmp(dstbuf, expect, r) != 0) { + printf("test %d: NOT OK: unexpected buffer content\n", testnum); + return 1; + } + if (dstbuf[expect_sz] != 0xAA) { + printf("test %d: NOT OK: corrupts memory with \"just enough\" bufsize\n", testnum); + return 1; + } + r = encode_base32hex(reverse_buf, 1024, dstbuf, expect_sz); + s = src; d = (char*)dstbuf; + expect_reverse = 0; + while (*s) { + if (*s != ' ' && *s != '=') { + *d++ = tolower(*s); + expect_reverse++; + } + s++; + } + if (r != expect_reverse) { + printf("test %d: NOT OK: REVERSE: expect size %d, got %d\n", testnum, expect_reverse, r); + return 1; + } else if (memcmp(reverse_buf, dstbuf, r) != 0) { + printf("test %d: NOT OK: REVERSE: unexpected buffer content\n", testnum); + return 1; + } + memset(dstbuf, 0xAA, 512); + for (i = 0; i < expect_sz; i++) { + r0 = decode_base32hex(dstbuf, src, i); + if (r0 > 0) { + printf("test %d: NOT OK: buffer size %d should not be enough\n", testnum, i); + return 1; + } + if (dstbuf[i] != 0xAA) { + printf("test %d: NOT OK: corrupts memory with bufsize %d\n", testnum, i); + return 1; + } + } + printf("test %d: ok\n", testnum); + return 0; } static int expect_junk_error(int testnum, char *src) { - char *buf[20]; - int r; + char *buf[20]; + int r; - r = decode_base32hex(buf, src, 20); - if (r != -1) { - printf("test %d: NOT OK: junk input not recognized\n", testnum); - return 1; - } - printf("test %d: ok\n", testnum); - return 0; + r = decode_base32hex(buf, src, 20); + if (r != -1) { + printf("test %d: NOT OK: junk input not recognized\n", testnum); + return 1; + } + printf("test %d: ok\n", testnum); + return 0; } int main(void) { - int ret = 0; - int t = 1; + int ret = 0; + int t = 1; - /* from http://tools.ietf.org/html/rfc4648#section-10 */ - ret |= ok_string_test(t++, "", ""); - ret |= ok_string_test(t++, "CO======", "f"); - ret |= ok_string_test(t++, "Co=====", "f"); - ret |= ok_string_test(t++, "cO====", "f"); - ret |= ok_string_test(t++, "co===", "f"); - ret |= ok_string_test(t++, "CO==", "f"); - ret |= ok_string_test(t++, "CO=", "f"); - ret |= ok_string_test(t++, "CO", "f"); + /* from http://tools.ietf.org/html/rfc4648#section-10 */ + ret |= ok_string_test(t++, "", ""); + ret |= ok_string_test(t++, "CO======", "f"); + ret |= ok_string_test(t++, "Co=====", "f"); + ret |= ok_string_test(t++, "cO====", "f"); + ret |= ok_string_test(t++, "co===", "f"); + ret |= ok_string_test(t++, "CO==", "f"); + ret |= ok_string_test(t++, "CO=", "f"); + ret |= ok_string_test(t++, "CO", "f"); - ret |= ok_string_test(t++, "CPNG====", "fo"); - ret |= ok_string_test(t++, "cPNG===", "fo"); - ret |= ok_string_test(t++, "cpNG==", "fo"); - ret |= ok_string_test(t++, "cpnG=", "fo"); - ret |= ok_string_test(t++, "cpng", "fo"); + ret |= ok_string_test(t++, "CPNG====", "fo"); + ret |= ok_string_test(t++, "cPNG===", "fo"); + ret |= ok_string_test(t++, "cpNG==", "fo"); + ret |= ok_string_test(t++, "cpnG=", "fo"); + ret |= ok_string_test(t++, "cpng", "fo"); - ret |= ok_string_test(t++, "CPNMU===", "foo"); - ret |= ok_string_test(t++, "CPnMU==", "foo"); - ret |= ok_string_test(t++, "CPnmu=", "foo"); - ret |= ok_string_test(t++, "cpNMU", "foo"); + ret |= ok_string_test(t++, "CPNMU===", "foo"); + ret |= ok_string_test(t++, "CPnMU==", "foo"); + ret |= ok_string_test(t++, "CPnmu=", "foo"); + ret |= ok_string_test(t++, "cpNMU", "foo"); - ret |= ok_string_test(t++, "CPNMUOG=", "foob"); - ret |= ok_string_test(t++, "CPNMUoG", "foob"); + ret |= ok_string_test(t++, "CPNMUOG=", "foob"); + ret |= ok_string_test(t++, "CPNMUoG", "foob"); - ret |= ok_string_test(t++, "CPNMUOJ1", "fooba"); - ret |= ok_string_test(t++, "cPnMuOj1", "fooba"); - ret |= ok_string_test(t++, "CpNmUoJ1", "fooba"); - ret |= ok_string_test(t++, "CpNm UoJ1", "fooba"); + ret |= ok_string_test(t++, "CPNMUOJ1", "fooba"); + ret |= ok_string_test(t++, "cPnMuOj1", "fooba"); + ret |= ok_string_test(t++, "CpNmUoJ1", "fooba"); + ret |= ok_string_test(t++, "CpNm UoJ1", "fooba"); - ret |= ok_string_test(t++, "CPNMUOJ1E8======", "foobar"); - ret |= ok_string_test(t++, "CPNMuOJ1E8=====", "foobar"); - ret |= ok_string_test(t++, "CpNMuOJ1E8====", "foobar"); - ret |= ok_string_test(t++, "CpNMuOJ1e8===", "foobar"); - ret |= ok_string_test(t++, "CpNmuOJ 1e8==", "foobar"); - ret |= ok_string_test(t++, "CpnmuOJ 1e8=", "foobar"); - ret |= ok_string_test(t++, "Cpn muOj 1e8", "foobar"); + ret |= ok_string_test(t++, "CPNMUOJ1E8======", "foobar"); + ret |= ok_string_test(t++, "CPNMuOJ1E8=====", "foobar"); + ret |= ok_string_test(t++, "CpNMuOJ1E8====", "foobar"); + ret |= ok_string_test(t++, "CpNMuOJ1e8===", "foobar"); + ret |= ok_string_test(t++, "CpNmuOJ 1e8==", "foobar"); + ret |= ok_string_test(t++, "CpnmuOJ 1e8=", "foobar"); + ret |= ok_string_test(t++, "Cpn muOj 1e8", "foobar"); - ret |= expect_junk_error(t++, "?m9vmF"); - ret |= expect_junk_error(t++, "%m9vmF"); - ret |= expect_junk_error(t++, "m&9vmF"); - ret |= expect_junk_error(t++, "m9-vmF"); - ret |= expect_junk_error(t++, "m9v*mF"); - ret |= expect_junk_error(t++, "m9v#mF"); - ret |= expect_junk_error(t++, "m9vm\x01F"); - ret |= expect_junk_error(t++, "m9vmF!"); - ret |= expect_junk_error(t++, "m9vmF."); - ret |= expect_junk_error(t++, "CpnmuOj/1e8x"); - ret |= expect_junk_error(t++, "CpnYmuOj1e8"); - ret |= expect_junk_error(t++, "CZpnmuOj1e8"); - ret |= expect_junk_error(t++, "CzpnmuOj1e8"); + ret |= expect_junk_error(t++, "?m9vmF"); + ret |= expect_junk_error(t++, "%m9vmF"); + ret |= expect_junk_error(t++, "m&9vmF"); + ret |= expect_junk_error(t++, "m9-vmF"); + ret |= expect_junk_error(t++, "m9v*mF"); + ret |= expect_junk_error(t++, "m9v#mF"); + ret |= expect_junk_error(t++, "m9vm\x01F"); + ret |= expect_junk_error(t++, "m9vmF!"); + ret |= expect_junk_error(t++, "m9vmF."); + ret |= expect_junk_error(t++, "CpnmuOj/1e8x"); + ret |= expect_junk_error(t++, "CpnYmuOj1e8"); + ret |= expect_junk_error(t++, "CZpnmuOj1e8"); + ret |= expect_junk_error(t++, "CzpnmuOj1e8"); - ret |= ok_string_test(t++, "MEQIMI6FJE5NI47PJAHV5QIGU1LV3JLJ", "\xb3\xb5\x2b\x48\xcf\x9b\x8b\x79\x10\xf9\x9a\xa3\xf2\xea\x50\xf0\x6b\xf1\xce\xb3"); + ret |= ok_string_test(t++, "MEQIMI6FJE5NI47PJAHV5QIGU1LV3JLJ", "\xb3\xb5\x2b\x48\xcf\x9b\x8b\x79\x10\xf9\x9a\xa3\xf2\xea\x50\xf0\x6b\xf1\xce\xb3"); - return ret; + return ret; } #endif diff --git a/base64.c b/base64.c index 8bca554..c2e103a 100644 --- a/base64.c +++ b/base64.c @@ -23,180 +23,180 @@ int decode_base64(void *dest, char *src, size_t dstsize) { - size_t processed = 0; - int full_bytes = 0; - unsigned char *dst = dest; + size_t processed = 0; + int full_bytes = 0; + unsigned char *dst = dest; - while (*src) { - int v; - if (*src >= 'A' && *src <= 'Z') - v = *src - 'A'; - else if (*src >= 'a' && *src <= 'z') - v = 26 + *src - 'a'; - else if (*src >= '0' && *src <= '9') - v = 52 + *src - '0'; - else if (*src == '+') - v = 62; - else if (*src == '/') - v = 63; - else if (isspace(*src) || *src == '=') { - src++; - continue; - } else { - /* any junk chars means input is corrupted */ - errno = EINVAL; - return -1; - } - src++; - if (processed % 4 == 0) { - if (dstsize <= 0) { - errno = EINVAL; - return -1; - } - dst[0] &= 0x03; - dst[0] |= (v << 2) & 0xFC; - processed++; - } else if (processed % 4 == 1) { - if (dstsize < 1) { - errno = EINVAL; - return -1; - } - dst[0] &= 0xFC; - dst[0] |= (v >> 4) & 0x03; - if (dstsize >= 2) { - dst[1] &= 0x0F; - dst[1] |= (v << 4) & 0xF0; - } - processed++; - full_bytes++; - } else if (processed % 4 == 2) { - if (dstsize < 2) { - errno = EINVAL; - return -1; - } - dst[1] &= 0xF0; - dst[1] |= (v >> 2) & 0x0F; - if (dstsize >= 3) { - dst[2] &= 0x3F; - dst[2] |= (v << 6) & 0xC0; - } - processed++; - full_bytes++; - } else { - if (dstsize <= 2) { - errno = EINVAL; - return -1; - } - dst[2] &= 0xC0; - dst[2] |= v & 0x3F; - processed++; - dst += 3; - dstsize -= 3; - full_bytes++; - } - } - return full_bytes; + while (*src) { + int v; + if (*src >= 'A' && *src <= 'Z') + v = *src - 'A'; + else if (*src >= 'a' && *src <= 'z') + v = 26 + *src - 'a'; + else if (*src >= '0' && *src <= '9') + v = 52 + *src - '0'; + else if (*src == '+') + v = 62; + else if (*src == '/') + v = 63; + else if (isspace(*src) || *src == '=') { + src++; + continue; + } else { + /* any junk chars means input is corrupted */ + errno = EINVAL; + return -1; + } + src++; + if (processed % 4 == 0) { + if (dstsize <= 0) { + errno = EINVAL; + return -1; + } + dst[0] &= 0x03; + dst[0] |= (v << 2) & 0xFC; + processed++; + } else if (processed % 4 == 1) { + if (dstsize < 1) { + errno = EINVAL; + return -1; + } + dst[0] &= 0xFC; + dst[0] |= (v >> 4) & 0x03; + if (dstsize >= 2) { + dst[1] &= 0x0F; + dst[1] |= (v << 4) & 0xF0; + } + processed++; + full_bytes++; + } else if (processed % 4 == 2) { + if (dstsize < 2) { + errno = EINVAL; + return -1; + } + dst[1] &= 0xF0; + dst[1] |= (v >> 2) & 0x0F; + if (dstsize >= 3) { + dst[2] &= 0x3F; + dst[2] |= (v << 6) & 0xC0; + } + processed++; + full_bytes++; + } else { + if (dstsize <= 2) { + errno = EINVAL; + return -1; + } + dst[2] &= 0xC0; + dst[2] |= v & 0x3F; + processed++; + dst += 3; + dstsize -= 3; + full_bytes++; + } + } + return full_bytes; } #ifdef TEST_PROGRAM static int ok_string_test(int testnum, char *src, char *expect) { - unsigned char dstbuf[512]; - int r, r0, i; - int expect_sz = strlen(expect); + unsigned char dstbuf[512]; + int r, r0, i; + int expect_sz = strlen(expect); - if (expect_sz >= 512) { - printf("test %d: NOT OK: internal *test* error, buffer too small for proper testing, FIXME\n", testnum); - return 1; - } - memset(dstbuf, 0xAA, 512); - r = decode_base64(dstbuf, src, expect_sz); - if (r != expect_sz) { - printf("test %d: NOT OK: expect size %d, got %d\n", testnum, expect_sz, r); - return 1; - } else if (memcmp(dstbuf, expect, r) != 0) { - printf("test %d: NOT OK: unexpected buffer content\n", testnum); - return 1; - } - if (dstbuf[expect_sz] != 0xAA) { - printf("test %d: NOT OK: corrupts memory with \"just enough\" bufsize\n", testnum); - return 1; - } - memset(dstbuf, 0xAA, 512); - for (i = 0; i < expect_sz; i++) { - r0 = decode_base64(dstbuf, src, i); - if (r0 > 0) { - printf("test %d: NOT OK: buffer size %d should not be enough\n", testnum, i); - return 1; - } - if (dstbuf[i] != 0xAA) { - printf("test %d: NOT OK: corrupts memory with bufsize %d\n", testnum, i); - return 1; - } - } - printf("test %d: ok\n", testnum); - return 0; + if (expect_sz >= 512) { + printf("test %d: NOT OK: internal *test* error, buffer too small for proper testing, FIXME\n", testnum); + return 1; + } + memset(dstbuf, 0xAA, 512); + r = decode_base64(dstbuf, src, expect_sz); + if (r != expect_sz) { + printf("test %d: NOT OK: expect size %d, got %d\n", testnum, expect_sz, r); + return 1; + } else if (memcmp(dstbuf, expect, r) != 0) { + printf("test %d: NOT OK: unexpected buffer content\n", testnum); + return 1; + } + if (dstbuf[expect_sz] != 0xAA) { + printf("test %d: NOT OK: corrupts memory with \"just enough\" bufsize\n", testnum); + return 1; + } + memset(dstbuf, 0xAA, 512); + for (i = 0; i < expect_sz; i++) { + r0 = decode_base64(dstbuf, src, i); + if (r0 > 0) { + printf("test %d: NOT OK: buffer size %d should not be enough\n", testnum, i); + return 1; + } + if (dstbuf[i] != 0xAA) { + printf("test %d: NOT OK: corrupts memory with bufsize %d\n", testnum, i); + return 1; + } + } + printf("test %d: ok\n", testnum); + return 0; } static int expect_junk_error(int testnum, char *src) { - char *buf[20]; - int r; + char *buf[20]; + int r; - r = decode_base64(buf, src, 20); - if (r != -1) { - printf("test %d: NOT OK: junk input not recognized\n", testnum); - return 1; - } - printf("test %d: ok\n", testnum); - return 0; + r = decode_base64(buf, src, 20); + if (r != -1) { + printf("test %d: NOT OK: junk input not recognized\n", testnum); + return 1; + } + printf("test %d: ok\n", testnum); + return 0; } int main(void) { - int ret = 0; + int ret = 0; - /* from http://en.wikipedia.org/wiki/Base64 */ - ret |= ok_string_test(1, "bGVhc3VyZS4=", "leasure."); - ret |= ok_string_test(2, "bGVhc3VyZS4", "leasure."); - ret |= ok_string_test(3, "ZWFzdXJlLg==", "easure."); - ret |= ok_string_test(4, "ZWFzdXJlLg=", "easure."); - ret |= ok_string_test(5, "ZWFzdXJlLg", "easure."); - ret |= ok_string_test(6, "YXN1cmUu", "asure."); - ret |= ok_string_test(7, "c3VyZS4=", "sure."); - ret |= ok_string_test(8, "c3VyZS4", "sure."); - ret |= ok_string_test(9, "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz\n" - "IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg\n" - "dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu\n" - "dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo\n" - "ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=", - "Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure."); - /* from http://tools.ietf.org/html/rfc4648#section-10 */ - ret |= ok_string_test(10, "", ""); - ret |= ok_string_test(11, "Zg==", "f"); - ret |= ok_string_test(12, "Zg=", "f"); - ret |= ok_string_test(13, "Zg", "f"); - ret |= ok_string_test(14, "Zm8=", "fo"); - ret |= ok_string_test(15, "Zm8", "fo"); - ret |= ok_string_test(16, "Zm9v", "foo"); - ret |= ok_string_test(17, "Zm9vYg==", "foob"); - ret |= ok_string_test(18, "Zm9vYg=", "foob"); - ret |= ok_string_test(19, "Zm9vYg", "foob"); - ret |= ok_string_test(20, "Zm9vYmE=", "fooba"); - ret |= ok_string_test(21, "Zm9vYmE", "fooba"); - ret |= ok_string_test(22, "Zm9vYmFy", "foobar"); + /* from http://en.wikipedia.org/wiki/Base64 */ + ret |= ok_string_test(1, "bGVhc3VyZS4=", "leasure."); + ret |= ok_string_test(2, "bGVhc3VyZS4", "leasure."); + ret |= ok_string_test(3, "ZWFzdXJlLg==", "easure."); + ret |= ok_string_test(4, "ZWFzdXJlLg=", "easure."); + ret |= ok_string_test(5, "ZWFzdXJlLg", "easure."); + ret |= ok_string_test(6, "YXN1cmUu", "asure."); + ret |= ok_string_test(7, "c3VyZS4=", "sure."); + ret |= ok_string_test(8, "c3VyZS4", "sure."); + ret |= ok_string_test(9, "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz\n" + "IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg\n" + "dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu\n" + "dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo\n" + "ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=", + "Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure."); + /* from http://tools.ietf.org/html/rfc4648#section-10 */ + ret |= ok_string_test(10, "", ""); + ret |= ok_string_test(11, "Zg==", "f"); + ret |= ok_string_test(12, "Zg=", "f"); + ret |= ok_string_test(13, "Zg", "f"); + ret |= ok_string_test(14, "Zm8=", "fo"); + ret |= ok_string_test(15, "Zm8", "fo"); + ret |= ok_string_test(16, "Zm9v", "foo"); + ret |= ok_string_test(17, "Zm9vYg==", "foob"); + ret |= ok_string_test(18, "Zm9vYg=", "foob"); + ret |= ok_string_test(19, "Zm9vYg", "foob"); + ret |= ok_string_test(20, "Zm9vYmE=", "fooba"); + ret |= ok_string_test(21, "Zm9vYmE", "fooba"); + ret |= ok_string_test(22, "Zm9vYmFy", "foobar"); - ret |= expect_junk_error(23, "?Zm9vYmFy"); - ret |= expect_junk_error(24, "Z%m9vYmFy"); - ret |= expect_junk_error(25, "Zm&9vYmFy"); - ret |= expect_junk_error(26, "Zm9-vYmFy"); - ret |= expect_junk_error(27, "Zm9v*YmFy"); - ret |= expect_junk_error(28, "Zm9vY#mFy"); - ret |= expect_junk_error(29, "Zm9vYm\x01Fy"); - ret |= expect_junk_error(30, "Zm9vYmF!y"); - ret |= expect_junk_error(31, "Zm9vYmFy."); + ret |= expect_junk_error(23, "?Zm9vYmFy"); + ret |= expect_junk_error(24, "Z%m9vYmFy"); + ret |= expect_junk_error(25, "Zm&9vYmFy"); + ret |= expect_junk_error(26, "Zm9-vYmFy"); + ret |= expect_junk_error(27, "Zm9v*YmFy"); + ret |= expect_junk_error(28, "Zm9vY#mFy"); + ret |= expect_junk_error(29, "Zm9vYm\x01Fy"); + ret |= expect_junk_error(30, "Zm9vYmF!y"); + ret |= expect_junk_error(31, "Zm9vYmFy."); - return ret; + return ret; } #endif diff --git a/caa.c b/caa.c index 9323b31..c0ac9e8 100644 --- a/caa.c +++ b/caa.c @@ -19,63 +19,63 @@ static struct rr* caa_parse(char *name, long ttl, int type, char *s) { - struct rr_caa *rr = getmem(sizeof(*rr)); - int algorithm, fp_type; + struct rr_caa *rr = getmem(sizeof(*rr)); + int algorithm, fp_type; - algorithm = extract_integer(&s, "algorithm", NULL); - if (algorithm < 0) return NULL; - if (algorithm != 1 && algorithm != 2 && algorithm != 3 && algorithm != 4) - return bitch("unsupported algorithm"); - rr->algorithm = algorithm; + algorithm = extract_integer(&s, "algorithm", NULL); + if (algorithm < 0) return NULL; + if (algorithm != 1 && algorithm != 2 && algorithm != 3 && algorithm != 4) + return bitch("unsupported algorithm"); + rr->algorithm = algorithm; - fp_type = extract_integer(&s, "fp type", NULL); - if (fp_type < 0) return NULL; - if (fp_type != 1 && fp_type != 2) - return bitch("unsupported fp_type"); - rr->fp_type = fp_type; + fp_type = extract_integer(&s, "fp type", NULL); + if (fp_type < 0) return NULL; + if (fp_type != 1 && fp_type != 2) + return bitch("unsupported fp_type"); + rr->fp_type = fp_type; - rr->fingerprint = extract_hex_binary_data(&s, "fingerprint", EXTRACT_EAT_WHITESPACE); - if (rr->fingerprint.length < 0) return NULL; - - if (rr->fp_type == 1 && rr->fingerprint.length != SHA1_BYTES) { - return bitch("wrong SHA-1 fingerprint length: %d bytes found, %d bytes expected", - rr->fingerprint.length, SHA1_BYTES); - } - if (rr->fp_type == 2 && rr->fingerprint.length != SHA256_BYTES) { - return bitch("wrong SHA-256 fingerprint length: %d bytes found, %d bytes expected", - rr->fingerprint.length, SHA256_BYTES); - } + rr->fingerprint = extract_hex_binary_data(&s, "fingerprint", EXTRACT_EAT_WHITESPACE); + if (rr->fingerprint.length < 0) return NULL; + + if (rr->fp_type == 1 && rr->fingerprint.length != SHA1_BYTES) { + return bitch("wrong SHA-1 fingerprint length: %d bytes found, %d bytes expected", + rr->fingerprint.length, SHA1_BYTES); + } + if (rr->fp_type == 2 && rr->fingerprint.length != SHA256_BYTES) { + return bitch("wrong SHA-256 fingerprint length: %d bytes found, %d bytes expected", + rr->fingerprint.length, SHA256_BYTES); + } - if (*s) { - return bitch("garbage after valid SSHFP data"); - } - return store_record(type, name, ttl, rr); + if (*s) { + return bitch("garbage after valid SSHFP data"); + } + return store_record(type, name, ttl, rr); } static char* caa_human(struct rr *rrv) { - RRCAST(caa); + RRCAST(caa); char ss[4096]; - char *s = ss; - int l; - int i; + char *s = ss; + int l; + int i; l = snprintf(s, 4096, "%u %u ", rr->algorithm, rr->fp_type); - s += l; - for (i = 0; i < rr->fingerprint.length; i++) { - l = snprintf(s, 4096-(s-ss), "%02X", (unsigned char)rr->fingerprint.data[i]); - s += l; - } + s += l; + for (i = 0; i < rr->fingerprint.length; i++) { + l = snprintf(s, 4096-(s-ss), "%02X", (unsigned char)rr->fingerprint.data[i]); + s += l; + } return quickstrdup_temp(ss); } static struct binary_data caa_wirerdata(struct rr *rrv) { - RRCAST(caa); + RRCAST(caa); - return compose_binary_data("11d", 1, - rr->algorithm, rr->fp_type, - rr->fingerprint); + return compose_binary_data("11d", 1, + rr->algorithm, rr->fp_type, + rr->fingerprint); } struct rr_methods caa_methods = { caa_parse, caa_human, caa_wirerdata, NULL, NULL }; diff --git a/carp.c b/carp.c index 30879dc..e88bb52 100644 --- a/carp.c +++ b/carp.c @@ -23,77 +23,77 @@ static void v(int is_croak, int is_x, int exit_code, const char *fmt, va_list ap void croak(int exit_code, const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - v(1, errno, exit_code, fmt, ap); - va_end(ap); + va_list ap; + va_start(ap, fmt); + v(1, errno, exit_code, fmt, ap); + va_end(ap); } void croakx(int exit_code, const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - v(1, -1, exit_code, fmt, ap); - va_end(ap); + va_list ap; + va_start(ap, fmt); + v(1, -1, exit_code, fmt, ap); + va_end(ap); } void * bitch(const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - if (!G.opt.no_output) { - fprintf(stderr, "%s:%d: ", file_info->name, file_info->line); - if (fmt != NULL) { - vfprintf(stderr, fmt, ap); - } - fprintf(stderr, "\n"); - } - va_end(ap); - G.exit_code = 1; - G.stats.error_count++; - file_info->paren_mode = 0; - if (G.opt.die_on_first_error) - exit(1); - return NULL; + va_list ap; + va_start(ap, fmt); + if (!G.opt.no_output) { + fprintf(stderr, "%s:%d: ", file_info->name, file_info->line); + if (fmt != NULL) { + vfprintf(stderr, fmt, ap); + } + fprintf(stderr, "\n"); + } + va_end(ap); + G.exit_code = 1; + G.stats.error_count++; + file_info->paren_mode = 0; + if (G.opt.die_on_first_error) + exit(1); + return NULL; } void * moan(char *file_name, int line, const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - if (!G.opt.no_output) { - fprintf(stderr, "%s:%d: ", file_name, line); - if (fmt != NULL) { - vfprintf(stderr, fmt, ap); - } - fprintf(stderr, "\n"); - } - va_end(ap); - G.exit_code = 1; - G.stats.error_count++; - if (G.opt.die_on_first_error) - exit(1); - return NULL; + va_list ap; + va_start(ap, fmt); + if (!G.opt.no_output) { + fprintf(stderr, "%s:%d: ", file_name, line); + if (fmt != NULL) { + vfprintf(stderr, fmt, ap); + } + fprintf(stderr, "\n"); + } + va_end(ap); + G.exit_code = 1; + G.stats.error_count++; + if (G.opt.die_on_first_error) + exit(1); + return NULL; } void v(int is_croak, int use_errno, int exit_code, const char *fmt, va_list ap) { - fprintf(stderr, "%s: ", thisprogname()); - if (fmt != NULL) { - vfprintf(stderr, fmt, ap); - if (use_errno >= 0) - fprintf(stderr, ": "); - } - if (use_errno >= 0) - fprintf(stderr, "%s\n", strerror(use_errno)); - else - fprintf(stderr, "\n"); - if (is_croak) - exit(exit_code); + fprintf(stderr, "%s: ", thisprogname()); + if (fmt != NULL) { + vfprintf(stderr, fmt, ap); + if (use_errno >= 0) + fprintf(stderr, ": "); + } + if (use_errno >= 0) + fprintf(stderr, "%s\n", strerror(use_errno)); + else + fprintf(stderr, "\n"); + if (is_croak) + exit(exit_code); } #if defined(__linux__) @@ -103,15 +103,15 @@ static char proggy[MAXPATHLEN]; const char *thisprogname(void) { #if defined(__FreeBSD__) - return getprogname(); + return getprogname(); #elif defined(__APPLE__) - return getprogname(); + return getprogname(); #elif defined(__sun__) - return getexecname(); + return getexecname(); #elif defined(__linux__) - if (readlink("/proc/self/exe", proggy, MAXPATHLEN) != -1) - return proggy; - return ""; + if (readlink("/proc/self/exe", proggy, MAXPATHLEN) != -1) + return proggy; + return ""; #else #error "unsupported OS" #endif diff --git a/cbtree.c b/cbtree.c index ecf351c..bc706ca 100644 --- a/cbtree.c +++ b/cbtree.c @@ -24,10 +24,10 @@ struct node { struct pool { - struct pool *next; - size_t pool_size; - size_t free_index; - char mem[0]; + struct pool *next; + size_t pool_size; + size_t free_index; + char mem[0]; }; static struct pool *internal = NULL; @@ -35,35 +35,35 @@ static struct pool *external = NULL; static int new_pool(struct pool **root, size_t size) { - struct pool *pool; - - size = (size + sizeof(void *) - 1) / sizeof(void *); - size *= sizeof(void *); - pool = malloc(size + sizeof(struct pool)); - if (!pool) { - return 1; - } - pool->next = *root; - pool->free_index = 0; - pool->pool_size = size; - *root = pool; - return 0; + struct pool *pool; + + size = (size + sizeof(void *) - 1) / sizeof(void *); + size *= sizeof(void *); + pool = malloc(size + sizeof(struct pool)); + if (!pool) { + return 1; + } + pool->next = *root; + pool->free_index = 0; + pool->pool_size = size; + *root = pool; + return 0; } static void *alloc(struct pool **root, size_t size) { - void *ret; - size = (size + sizeof(void *) - 1) / sizeof(void *); - size *= sizeof(void *); - if (!*root) - if (new_pool(root, size > 256000 ? size : 256000) != 0) - return NULL; - if ((*root)->pool_size - (*root)->free_index < size) - if (new_pool(root, size > 256000 ? size : 256000) != 0) - return NULL; - ret = (*root)->mem + (*root)->free_index; - (*root)->free_index += size; - return ret; + void *ret; + size = (size + sizeof(void *) - 1) / sizeof(void *); + size *= sizeof(void *); + if (!*root) + if (new_pool(root, size > 256000 ? size : 256000) != 0) + return NULL; + if ((*root)->pool_size - (*root)->free_index < size) + if (new_pool(root, size > 256000 ? size : 256000) != 0) + return NULL; + ret = (*root)->mem + (*root)->free_index; + (*root)->free_index += size; + return ret; } /* main code */ @@ -75,318 +75,318 @@ cbtree_find(struct cbtree *t, const char *u) const size_t ulen = strlen(u); uint8_t *p = t->root; - /* Test for empty tree */ - if (!p) return NULL; + /* Test for empty tree */ + if (!p) return NULL; /* Walk tree for best member */ - while (1 & (intptr_t) p) { - struct node *q = (void *)(p - 1); - /* Calculate direction */ - int direction; - uint8_t c = 0; - - if (q->byte < ulen) - c = ubytes[q->byte]; - direction = (1 + (q->otherbits | c)) >> 8; - - p = q->child[direction]; - } - - /* The leaves contain "[data ptr][string]" */ - if (strcmp(u, (const char *)(p + sizeof(intptr_t))) == 0) - return (intptr_t *)p; - return NULL; + while (1 & (intptr_t) p) { + struct node *q = (void *)(p - 1); + /* Calculate direction */ + int direction; + uint8_t c = 0; + + if (q->byte < ulen) + c = ubytes[q->byte]; + direction = (1 + (q->otherbits | c)) >> 8; + + p = q->child[direction]; + } + + /* The leaves contain "[data ptr][string]" */ + if (strcmp(u, (const char *)(p + sizeof(intptr_t))) == 0) + return (intptr_t *)p; + return NULL; } intptr_t* cbtree_insert(struct cbtree *t, const char *u) { - const uint8_t *const ubytes = (void *) u; - const size_t ulen = strlen(u); - uint8_t *p = t->root; - - /* Deal with inserting into an empty tree */ - if (!p) { - char *x = alloc(&external, ulen + 1 + sizeof(intptr_t)); - if (!x) - return NULL; - *((intptr_t *)x) = 0; - memcpy(x + sizeof(intptr_t), u, ulen + 1); - t->root = x; - return (intptr_t *)x; - } + const uint8_t *const ubytes = (void *) u; + const size_t ulen = strlen(u); + uint8_t *p = t->root; + + /* Deal with inserting into an empty tree */ + if (!p) { + char *x = alloc(&external, ulen + 1 + sizeof(intptr_t)); + if (!x) + return NULL; + *((intptr_t *)x) = 0; + memcpy(x + sizeof(intptr_t), u, ulen + 1); + t->root = x; + return (intptr_t *)x; + } /* Walk tree for best member */ - while (1 & (intptr_t) p) { - struct node *q = (void *)(p - 1); - /* Calculate direction */ - int direction; - uint8_t c = 0; - - if (q->byte < ulen) - c = ubytes[q->byte]; - direction = (1 + (q->otherbits | c)) >> 8; - - p = q->child[direction]; - } - - /* Find the critical bit */ - /* 1: Find differing byte */ - uint32_t newbyte; - uint32_t newotherbits; - - for (newbyte = 0; newbyte < ulen; ++newbyte) { - if (p[sizeof(intptr_t) + newbyte] != ubytes[newbyte]) { - newotherbits = p[sizeof(intptr_t) + newbyte] ^ ubytes[newbyte]; - goto different_byte_found; - } - } - - if (p[sizeof(intptr_t) + newbyte] != 0) { - newotherbits = p[sizeof(intptr_t) + newbyte]; - goto different_byte_found; - } - return (intptr_t *)p; + while (1 & (intptr_t) p) { + struct node *q = (void *)(p - 1); + /* Calculate direction */ + int direction; + uint8_t c = 0; + + if (q->byte < ulen) + c = ubytes[q->byte]; + direction = (1 + (q->otherbits | c)) >> 8; + + p = q->child[direction]; + } + + /* Find the critical bit */ + /* 1: Find differing byte */ + uint32_t newbyte; + uint32_t newotherbits; + + for (newbyte = 0; newbyte < ulen; ++newbyte) { + if (p[sizeof(intptr_t) + newbyte] != ubytes[newbyte]) { + newotherbits = p[sizeof(intptr_t) + newbyte] ^ ubytes[newbyte]; + goto different_byte_found; + } + } + + if (p[sizeof(intptr_t) + newbyte] != 0) { + newotherbits = p[sizeof(intptr_t) + newbyte]; + goto different_byte_found; + } + return (intptr_t *)p; different_byte_found: - /* 2: Find differing bit */ - newotherbits |= newotherbits >> 1; - newotherbits |= newotherbits >> 2; - newotherbits |= newotherbits >> 4; - newotherbits = (newotherbits & ~(newotherbits >> 1)) ^ 255; - uint8_t c = p[sizeof(intptr_t) + newbyte]; - int newdirection = (1 + (newotherbits | c)) >> 8; - - /* Insert new string */ - - /* 1: Allocate new node structure */ - struct node *newnode; - - newnode = alloc(&internal, sizeof(struct node)); - if (!newnode) - return NULL; - - char *x = alloc(&external, ulen + 1 + sizeof(intptr_t)); - if (!x) - return NULL; - *((intptr_t *)x) = 0; - memcpy(x + sizeof(intptr_t), ubytes, ulen + 1); - - newnode->byte = newbyte; - newnode->otherbits = newotherbits; - newnode->child[1 - newdirection] = x; - - /* 2: Insert new node */ - void **wherep = &t->root; - for (;;) { - uint8_t *p = *wherep; - if (!(1 & (intptr_t) p)) break; - struct node *q = (void *) (p - 1); - if (q->byte > newbyte) break; - if (q->byte == newbyte && q->otherbits > newotherbits) break; - uint8_t c = 0; - if (q->byte < ulen) c = ubytes[q->byte]; - const int direction = (1 + (q->otherbits | c)) >> 8; - wherep = q->child + direction; - } - - newnode->child[newdirection] = *wherep; - *wherep = (void *) (1 + (char *) newnode); - - return (intptr_t *)x; + /* 2: Find differing bit */ + newotherbits |= newotherbits >> 1; + newotherbits |= newotherbits >> 2; + newotherbits |= newotherbits >> 4; + newotherbits = (newotherbits & ~(newotherbits >> 1)) ^ 255; + uint8_t c = p[sizeof(intptr_t) + newbyte]; + int newdirection = (1 + (newotherbits | c)) >> 8; + + /* Insert new string */ + + /* 1: Allocate new node structure */ + struct node *newnode; + + newnode = alloc(&internal, sizeof(struct node)); + if (!newnode) + return NULL; + + char *x = alloc(&external, ulen + 1 + sizeof(intptr_t)); + if (!x) + return NULL; + *((intptr_t *)x) = 0; + memcpy(x + sizeof(intptr_t), ubytes, ulen + 1); + + newnode->byte = newbyte; + newnode->otherbits = newotherbits; + newnode->child[1 - newdirection] = x; + + /* 2: Insert new node */ + void **wherep = &t->root; + for (;;) { + uint8_t *p = *wherep; + if (!(1 & (intptr_t) p)) break; + struct node *q = (void *) (p - 1); + if (q->byte > newbyte) break; + if (q->byte == newbyte && q->otherbits > newotherbits) break; + uint8_t c = 0; + if (q->byte < ulen) c = ubytes[q->byte]; + const int direction = (1 + (q->otherbits | c)) >> 8; + wherep = q->child + direction; + } + + newnode->child[newdirection] = *wherep; + *wherep = (void *) (1 + (char *) newnode); + + return (intptr_t *)x; } intptr_t cbtree_delete(struct cbtree *t, const char *u) { - const uint8_t *ubytes = (void *) u; - const size_t ulen = strlen(u); - uint8_t *p = t->root; - void **wherep = &t->root; - void **whereq = 0; - struct node *q = 0; - int direction = 0; - intptr_t ret; - - /* Deal with deleting from an empty tree */ - if (!p) return 0; - - /* Walk the tree for the best match */ - while (1 & (intptr_t) p) { - whereq = wherep; - q = (void *) (p - 1); - uint8_t c = 0; - if (q->byte < ulen) c = ubytes[q->byte]; - direction = (1 + (q->otherbits | c)) >> 8; - wherep = q->child + direction; - p = *wherep; - } - - /* Check the best match */ - if (0 != strcmp(u, (const char *)(p + sizeof(intptr_t)))) - return 0; - ret = *((intptr_t *)p); - - /* Remove the element and/or node */ - if (!whereq) { - t->root = 0; - return ret; - } - - *whereq = q->child[1 - direction]; - // free(q); - - return ret; + const uint8_t *ubytes = (void *) u; + const size_t ulen = strlen(u); + uint8_t *p = t->root; + void **wherep = &t->root; + void **whereq = 0; + struct node *q = 0; + int direction = 0; + intptr_t ret; + + /* Deal with deleting from an empty tree */ + if (!p) return 0; + + /* Walk the tree for the best match */ + while (1 & (intptr_t) p) { + whereq = wherep; + q = (void *) (p - 1); + uint8_t c = 0; + if (q->byte < ulen) c = ubytes[q->byte]; + direction = (1 + (q->otherbits | c)) >> 8; + wherep = q->child + direction; + p = *wherep; + } + + /* Check the best match */ + if (0 != strcmp(u, (const char *)(p + sizeof(intptr_t)))) + return 0; + ret = *((intptr_t *)p); + + /* Remove the element and/or node */ + if (!whereq) { + t->root = 0; + return ret; + } + + *whereq = q->child[1 - direction]; + // free(q); + + return ret; } static void traverse(void *top) { - uint8_t *p = top; - - if (1 & (intptr_t) p) { - struct node *q = (void *) (p - 1); - traverse(q->child[0]); - traverse(q->child[1]); - // free(q); - } else { - // free(p); - } + uint8_t *p = top; + + if (1 & (intptr_t) p) { + struct node *q = (void *) (p - 1); + traverse(q->child[0]); + traverse(q->child[1]); + // free(q); + } else { + // free(p); + } } void cbtree_clear(struct cbtree *t) { - if (t->root) traverse(t->root); - t->root = NULL; + if (t->root) traverse(t->root); + t->root = NULL; } static int allprefixed_traverse(uint8_t *top, int (*handle)(const char *, intptr_t *, void *), void *arg) { - int direction; - - /* Deal with an internal node */ - if (1 & (intptr_t) top) { - struct node *q = (void *) (top - 1); - for (direction = 0; direction < 2; ++direction) - switch(allprefixed_traverse(q->child[direction], handle, arg)) { - case 1: break; - case 0: return 0; - default: return -1; - } - return 1; - } - - /* Deal with an external node */ - return handle((const char *)(top + sizeof(intptr_t)), (intptr_t *)top, arg); + int direction; + + /* Deal with an internal node */ + if (1 & (intptr_t) top) { + struct node *q = (void *) (top - 1); + for (direction = 0; direction < 2; ++direction) + switch(allprefixed_traverse(q->child[direction], handle, arg)) { + case 1: break; + case 0: return 0; + default: return -1; + } + return 1; + } + + /* Deal with an external node */ + return handle((const char *)(top + sizeof(intptr_t)), (intptr_t *)top, arg); } int cbtree_allprefixed(struct cbtree *t, const char *prefix, - int (*handle)(const char *, intptr_t *, void *), - void *arg) + int (*handle)(const char *, intptr_t *, void *), + void *arg) { - const uint8_t *ubytes = (void *) prefix; - const size_t ulen = strlen(prefix); - uint8_t *p = t->root; - uint8_t *top = p; - int i; - - if (!p) return 1; /* S = $\emptyset$ */ - - /* Walk tree, maintaining top pointer */ - while (1 & (intptr_t) p) { - struct node *q = (void *) (p - 1); - uint8_t c = 0; - if (q->byte < ulen) c = ubytes[q->byte]; - const int direction = (1 + (q->otherbits | c)) >> 8; - p = q->child[direction]; - if (q->byte < ulen) top = p; - } - - /* Check prefix */ - for (i = 0; i < ulen; ++i) { - if (p[i+sizeof(intptr_t)] != ubytes[i]) return 1; - } - - return allprefixed_traverse(top, handle, arg); + const uint8_t *ubytes = (void *) prefix; + const size_t ulen = strlen(prefix); + uint8_t *p = t->root; + uint8_t *top = p; + int i; + + if (!p) return 1; /* S = $\emptyset$ */ + + /* Walk tree, maintaining top pointer */ + while (1 & (intptr_t) p) { + struct node *q = (void *) (p - 1); + uint8_t c = 0; + if (q->byte < ulen) c = ubytes[q->byte]; + const int direction = (1 + (q->otherbits | c)) >> 8; + p = q->child[direction]; + if (q->byte < ulen) top = p; + } + + /* Check prefix */ + for (i = 0; i < ulen; ++i) { + if (p[i+sizeof(intptr_t)] != ubytes[i]) return 1; + } + + return allprefixed_traverse(top, handle, arg); } static const char *byte_to_binary(int x) { - static char b[9]; - int z; + static char b[9]; + int z; - b[0] = '\0'; - for (z = 128; z > 0; z >>= 1) - strcat(b, ((x & z) == z) ? "1" : "0"); + b[0] = '\0'; + for (z = 128; z > 0; z >>= 1) + strcat(b, ((x & z) == z) ? "1" : "0"); - return b; + return b; } static void traverse_dump(void *top, int level, int byte) { - uint8_t *p = top; - int i; - - for (i = 0; i < level; i++) printf(" "); - if (1 & (intptr_t) p) { - struct node *q = (void *) (p - 1); - printf("[byte(%d),otherbits(%s)]\n", q->byte, byte_to_binary(q->otherbits)); - traverse_dump(q->child[0], level + 1, q->byte); - traverse_dump(q->child[1], level + 1, q->byte); - } else { - const size_t ulen = strlen((char *)(p + sizeof(intptr_t))); - int c = byte < ulen ? p[sizeof(intptr_t) + byte] : 0; - printf("\"%s\" (%s)\n", p + sizeof(intptr_t), byte_to_binary(c)); - } + uint8_t *p = top; + int i; + + for (i = 0; i < level; i++) printf(" "); + if (1 & (intptr_t) p) { + struct node *q = (void *) (p - 1); + printf("[byte(%d),otherbits(%s)]\n", q->byte, byte_to_binary(q->otherbits)); + traverse_dump(q->child[0], level + 1, q->byte); + traverse_dump(q->child[1], level + 1, q->byte); + } else { + const size_t ulen = strlen((char *)(p + sizeof(intptr_t))); + int c = byte < ulen ? p[sizeof(intptr_t) + byte] : 0; + printf("\"%s\" (%s)\n", p + sizeof(intptr_t), byte_to_binary(c)); + } } void cbtree_dump(struct cbtree *t) { - if (t->root) - traverse_dump(t->root, 0, 0); - printf("\n"); + if (t->root) + traverse_dump(t->root, 0, 0); + printf("\n"); } char* cbtree_next(struct cbtree *t, const char *u, intptr_t *data) { - const uint8_t *ubytes = (void *) u; - const size_t ulen = strlen(u); - uint8_t *p = t->root; - uint8_t *branch = NULL; - - if (!p) return NULL; - - /* Walk tree, maintaining top pointer */ - while (1 & (intptr_t) p) { - struct node *q = (void *) (p - 1); - uint8_t c = 0; - if (q->byte < ulen) c = ubytes[q->byte]; - const int direction = (1 + (q->otherbits | c)) >> 8; - if (direction == 0) - branch = q->child[1]; - p = q->child[direction]; - } - - /* check whether what we found is what we are looking for already */ - if (strcmp((char *)(p + sizeof(intptr_t)), u) > 0) { - if (data) *data = *((intptr_t *)p); - return (char *)(p + sizeof(intptr_t)); - } - - if (!branch) return NULL; - - /* select the lowest value on the branch */ - p = branch; - while (1 & (intptr_t) p) { - struct node *q = (void *) (p - 1); - p = q->child[0]; - } - if (data) *data = *((intptr_t *)p); - return (char *)(p + sizeof(intptr_t)); + const uint8_t *ubytes = (void *) u; + const size_t ulen = strlen(u); + uint8_t *p = t->root; + uint8_t *branch = NULL; + + if (!p) return NULL; + + /* Walk tree, maintaining top pointer */ + while (1 & (intptr_t) p) { + struct node *q = (void *) (p - 1); + uint8_t c = 0; + if (q->byte < ulen) c = ubytes[q->byte]; + const int direction = (1 + (q->otherbits | c)) >> 8; + if (direction == 0) + branch = q->child[1]; + p = q->child[direction]; + } + + /* check whether what we found is what we are looking for already */ + if (strcmp((char *)(p + sizeof(intptr_t)), u) > 0) { + if (data) *data = *((intptr_t *)p); + return (char *)(p + sizeof(intptr_t)); + } + + if (!branch) return NULL; + + /* select the lowest value on the branch */ + p = branch; + while (1 & (intptr_t) p) { + struct node *q = (void *) (p - 1); + p = q->child[0]; + } + if (data) *data = *((intptr_t *)p); + return (char *)(p + sizeof(intptr_t)); } diff --git a/cbtree.h b/cbtree.h index 1dfe83e..154655a 100644 --- a/cbtree.h +++ b/cbtree.h @@ -47,8 +47,8 @@ intptr_t cbtree_delete(struct cbtree *t, const char *u); void cbtree_clear(struct cbtree *t); int cbtree_allprefixed(struct cbtree *t, const char *prefix, - int (*handle)(const char *, intptr_t *, void *), - void *arg); + int (*handle)(const char *, intptr_t *, void *), + void *arg); void cbtree_dump(struct cbtree *t); diff --git a/cert.c b/cert.c index d4b551d..6fb3336 100644 --- a/cert.c +++ b/cert.c @@ -26,115 +26,115 @@ static int extract_certificate_type(char **s, char *what) { - int type; - char *str_type; - - if (isdigit(**s)) { - type = extract_integer(s, what, NULL); - if (type >= 1 && type <= 8) - return type; - if (type == 253 || type == 254) - return type; - if (type >= 65280 && type <= 65534) - return type; - if (type < 0 || type > 65535) { - bitch("bad certificate type %d", type); - return -1; - } - if (type == 0 || type == 255 || type == 65535) { - bitch("certificate type %d is reserved by IANA", type); - return -1; - } - bitch("certificate type %d is unassigned", type); - return -1; - } else { - str_type = extract_label(s, what, "temporary"); - if (!str_type) return -1; - if (strcmp(str_type, "pkix") == 0) - return 1; - if (strcmp(str_type, "spki") == 0) - return 2; - if (strcmp(str_type, "pgp") == 0) - return 3; - if (strcmp(str_type, "ipkix") == 0) - return 4; - if (strcmp(str_type, "ispki") == 0) - return 5; - if (strcmp(str_type, "ipgp") == 0) - return 6; - if (strcmp(str_type, "acpkix") == 0) - return 7; - if (strcmp(str_type, "iacpkix") == 0) - return 8; - if (strcmp(str_type, "uri") == 0) - return 253; - if (strcmp(str_type, "oid") == 0) - return 254; - bitch("bad certificate type %s", str_type); - return -1; - } + int type; + char *str_type; + + if (isdigit(**s)) { + type = extract_integer(s, what, NULL); + if (type >= 1 && type <= 8) + return type; + if (type == 253 || type == 254) + return type; + if (type >= 65280 && type <= 65534) + return type; + if (type < 0 || type > 65535) { + bitch("bad certificate type %d", type); + return -1; + } + if (type == 0 || type == 255 || type == 65535) { + bitch("certificate type %d is reserved by IANA", type); + return -1; + } + bitch("certificate type %d is unassigned", type); + return -1; + } else { + str_type = extract_label(s, what, "temporary"); + if (!str_type) return -1; + if (strcmp(str_type, "pkix") == 0) + return 1; + if (strcmp(str_type, "spki") == 0) + return 2; + if (strcmp(str_type, "pgp") == 0) + return 3; + if (strcmp(str_type, "ipkix") == 0) + return 4; + if (strcmp(str_type, "ispki") == 0) + return 5; + if (strcmp(str_type, "ipgp") == 0) + return 6; + if (strcmp(str_type, "acpkix") == 0) + return 7; + if (strcmp(str_type, "iacpkix") == 0) + return 8; + if (strcmp(str_type, "uri") == 0) + return 253; + if (strcmp(str_type, "oid") == 0) + return 254; + bitch("bad certificate type %s", str_type); + return -1; + } } static struct rr* cert_parse(char *name, long ttl, int type, char *s) { - struct rr_cert *rr = getmem(sizeof(*rr)); - int cert_type, key_tag, alg; - - cert_type = extract_certificate_type(&s, "certificate type"); - if (cert_type < 0) return NULL; - rr->type = cert_type; - - key_tag = extract_integer(&s, "key tag", NULL); - if (key_tag < 0) return NULL; - if (key_tag > 65535) - return bitch("bad key tag"); - rr->key_tag = key_tag; - - if (isdigit(*s)) { - alg = extract_integer(&s, "algorithm", NULL); - if (alg < 0) return NULL; - if (alg > 255) return bitch("bad algorithm"); - if (alg != 0) { /* 0 is just fine */ - if (algorithm_type(alg) == ALG_UNSUPPORTED) - return bitch("bad algorithm %d", alg); - } - } else { - alg = extract_algorithm(&s, "algorithm"); - if (alg == ALG_UNSUPPORTED) return NULL; - } - rr->algorithm = alg; - - if (alg == 0 && key_tag != 0) { - /* we might want to bitch here, but RFC says "SHOULD", so we don't */ - } - - rr->certificate = extract_base64_binary_data(&s, "certificate"); - if (rr->certificate.length < 0) return NULL; - /* TODO validate cert length based on algorithm */ - - if (*s) { - return bitch("garbage after valid CERT data"); - } - return store_record(type, name, ttl, rr); + struct rr_cert *rr = getmem(sizeof(*rr)); + int cert_type, key_tag, alg; + + cert_type = extract_certificate_type(&s, "certificate type"); + if (cert_type < 0) return NULL; + rr->type = cert_type; + + key_tag = extract_integer(&s, "key tag", NULL); + if (key_tag < 0) return NULL; + if (key_tag > 65535) + return bitch("bad key tag"); + rr->key_tag = key_tag; + + if (isdigit(*s)) { + alg = extract_integer(&s, "algorithm", NULL); + if (alg < 0) return NULL; + if (alg > 255) return bitch("bad algorithm"); + if (alg != 0) { /* 0 is just fine */ + if (algorithm_type(alg) == ALG_UNSUPPORTED) + return bitch("bad algorithm %d", alg); + } + } else { + alg = extract_algorithm(&s, "algorithm"); + if (alg == ALG_UNSUPPORTED) return NULL; + } + rr->algorithm = alg; + + if (alg == 0 && key_tag != 0) { + /* we might want to bitch here, but RFC says "SHOULD", so we don't */ + } + + rr->certificate = extract_base64_binary_data(&s, "certificate"); + if (rr->certificate.length < 0) return NULL; + /* TODO validate cert length based on algorithm */ + + if (*s) { + return bitch("garbage after valid CERT data"); + } + return store_record(type, name, ttl, rr); } static char* cert_human(struct rr *rrv) { - RRCAST(cert); + RRCAST(cert); char s[1024]; snprintf(s, 1024, "%d %d %d ...", - rr->type, rr->key_tag, rr->algorithm); + rr->type, rr->key_tag, rr->algorithm); return quickstrdup_temp(s); } static struct binary_data cert_wirerdata(struct rr *rrv) { - RRCAST(cert); + RRCAST(cert); - return compose_binary_data("221d", 1, - rr->type, rr->key_tag, rr->algorithm, - rr->certificate); + return compose_binary_data("221d", 1, + rr->type, rr->key_tag, rr->algorithm, + rr->certificate); } struct rr_methods cert_methods = { cert_parse, cert_human, cert_wirerdata, NULL, NULL }; diff --git a/cname.c b/cname.c index c63680e..23f07ac 100644 --- a/cname.c +++ b/cname.c @@ -19,58 +19,58 @@ static struct rr *cname_parse(char *name, long ttl, int type, char *s) { - struct rr_cname *rr = getmem(sizeof(*rr)); + struct rr_cname *rr = getmem(sizeof(*rr)); - rr->cname = extract_name(&s, "cname", 0); - if (!rr->cname) - return NULL; - if (*s) { - return bitch("garbage after valid CNAME data"); - } + rr->cname = extract_name(&s, "cname", 0); + if (!rr->cname) + return NULL; + if (*s) { + return bitch("garbage after valid CNAME data"); + } - return store_record(type, name, ttl, rr); + return store_record(type, name, ttl, rr); } static char* cname_human(struct rr *rrv) { - RRCAST(cname); + RRCAST(cname); return rr->cname; } static struct binary_data cname_wirerdata(struct rr *rrv) { - RRCAST(cname); - return name2wire_name(rr->cname); + RRCAST(cname); + return name2wire_name(rr->cname); } static void* cname_validate_set(struct rr_set *rr_set) { - struct rr *rr; - struct rr_set *another_set; - struct named_rr *named_rr; - int count; + struct rr *rr; + struct rr_set *another_set; + struct named_rr *named_rr; + int count; - if (G.opt.policy_checks[POLICY_CNAME_OTHER_DATA]) { - if (rr_set->count > 1) { - rr = rr_set->tail; - return moan(rr->file_name, rr->line, "CNAME and other data"); - } - named_rr = rr_set->named_rr; - count = get_rr_set_count(named_rr); - if (count > 1) { - another_set = find_rr_set_in_named_rr(named_rr, T_RRSIG); - if (another_set) - count -= another_set->count; - another_set = find_rr_set_in_named_rr(named_rr, T_NSEC); - if (another_set) - count -= another_set->count; - if (count > 1) { - rr = rr_set->tail; - return moan(rr->file_name, rr->line, "CNAME and other data"); - } - } - } - return NULL; + if (G.opt.policy_checks[POLICY_CNAME_OTHER_DATA]) { + if (rr_set->count > 1) { + rr = rr_set->tail; + return moan(rr->file_name, rr->line, "CNAME and other data"); + } + named_rr = rr_set->named_rr; + count = get_rr_set_count(named_rr); + if (count > 1) { + another_set = find_rr_set_in_named_rr(named_rr, T_RRSIG); + if (another_set) + count -= another_set->count; + another_set = find_rr_set_in_named_rr(named_rr, T_NSEC); + if (another_set) + count -= another_set->count; + if (count > 1) { + rr = rr_set->tail; + return moan(rr->file_name, rr->line, "CNAME and other data"); + } + } + } + return NULL; } struct rr_methods cname_methods = { cname_parse, cname_human, cname_wirerdata, cname_validate_set, NULL }; diff --git a/common.h b/common.h index 6bcd40e..6f94bc1 100644 --- a/common.h +++ b/common.h @@ -12,29 +12,29 @@ struct generate_template_piece; struct generate_template_piece { - char *constant_string; - struct generate_template_piece *next; + char *constant_string; + struct generate_template_piece *next; }; #define LINEBUFSZ 2048 struct file_info { - struct file_info *next; - FILE *file; - int line; - int paren_mode; - char buf[LINEBUFSZ]; - char *current_origin; + struct file_info *next; + FILE *file; + int line; + int paren_mode; + char buf[LINEBUFSZ]; + char *current_origin; - int generate_cur; - int generate_lim; - char *generate_type; - struct generate_template_piece *generate_lhs; - struct generate_template_piece *generate_rhs; + int generate_cur; + int generate_lim; + char *generate_type; + struct generate_template_piece *generate_lhs; + struct generate_template_piece *generate_rhs; - /* must be last struct member */ - char name[0]; + /* must be last struct member */ + char name[0]; }; extern struct file_info *file_info; @@ -55,38 +55,38 @@ extern struct file_info *file_info; #define MAX_TIMES_TO_CHECK 32 struct globals { - struct stats { - int names_count; - int rr_count; - int rrset_count; - int error_count; - int skipped_dup_rr_count; - int soa_rr_count; - int signatures_verified; - int delegations; - int not_authoritative; - int nsec3_count; - } stats; - struct command_line_options - { - int die_on_first_error; - int no_output; - int summary; - int verbose; - char *include_path; - int include_path_specified; - char *first_origin; - int n_times_to_check; - uint32_t times_to_check[MAX_TIMES_TO_CHECK]; - char policy_checks[N_POLICY_CHECKS]; - int n_threads; - int soa_minttl_as_default_ttl; - } opt; - int exit_code; - long default_ttl; - int nsec3_present; - int nsec3_opt_out_present; - int dnssec_active; + struct stats { + int names_count; + int rr_count; + int rrset_count; + int error_count; + int skipped_dup_rr_count; + int soa_rr_count; + int signatures_verified; + int delegations; + int not_authoritative; + int nsec3_count; + } stats; + struct command_line_options + { + int die_on_first_error; + int no_output; + int summary; + int verbose; + char *include_path; + int include_path_specified; + char *first_origin; + int n_times_to_check; + uint32_t times_to_check[MAX_TIMES_TO_CHECK]; + char policy_checks[N_POLICY_CHECKS]; + int n_threads; + int soa_minttl_as_default_ttl; + } opt; + int exit_code; + long default_ttl; + int nsec3_present; + int nsec3_opt_out_present; + int dnssec_active; }; extern struct globals G; diff --git a/dhcid.c b/dhcid.c index e8f7147..cafce1f 100644 --- a/dhcid.c +++ b/dhcid.c @@ -21,35 +21,35 @@ static struct rr* dhcid_parse(char *name, long ttl, int type, char *s) { - struct rr_dhcid *rr = getmem(sizeof(*rr)); - struct binary_data data; + struct rr_dhcid *rr = getmem(sizeof(*rr)); + struct binary_data data; - data = extract_base64_binary_data(&s, "rdata"); - if (data.length < 0) return NULL; + data = extract_base64_binary_data(&s, "rdata"); + if (data.length < 0) return NULL; - if (data.length < 3) - return bitch("rdata too short"); + if (data.length < 3) + return bitch("rdata too short"); - rr->id_type = data.data[0]*256 + data.data[1]; - if (rr->id_type > 2) - return bitch("unsupported identifier type %s", rr->id_type); + rr->id_type = data.data[0]*256 + data.data[1]; + if (rr->id_type > 2) + return bitch("unsupported identifier type %s", rr->id_type); - rr->digest_type = data.data[2]; - if (rr->digest_type != 1) - return bitch("unsupported digest type %s", rr->digest_type); + rr->digest_type = data.data[2]; + if (rr->digest_type != 1) + return bitch("unsupported digest type %s", rr->digest_type); - if (data.length != 35) - return bitch("wrong digest length, must be 32 for SHA-256"); + if (data.length != 35) + return bitch("wrong digest length, must be 32 for SHA-256"); - /* let's cheat a bit */ - data.length -= 3; - data.data += 3; - rr->digest = data; + /* let's cheat a bit */ + data.length -= 3; + data.data += 3; + rr->digest = data; - if (*s) { - return bitch("garbage after valid DHCID data"); - } - return store_record(type, name, ttl, rr); + if (*s) { + return bitch("garbage after valid DHCID data"); + } + return store_record(type, name, ttl, rr); } static char* dhcid_human(struct rr *rrv) @@ -59,10 +59,10 @@ static char* dhcid_human(struct rr *rrv) static struct binary_data dhcid_wirerdata(struct rr *rrv) { - RRCAST(dhcid); + RRCAST(dhcid); - return compose_binary_data("21d", 1, - rr->id_type, rr->digest_type, rr->digest); + return compose_binary_data("21d", 1, + rr->id_type, rr->digest_type, rr->digest); } struct rr_methods dhcid_methods = { dhcid_parse, dhcid_human, dhcid_wirerdata, NULL, NULL }; diff --git a/dlv.c b/dlv.c index 8e7d078..2278f30 100644 --- a/dlv.c +++ b/dlv.c @@ -19,80 +19,80 @@ static struct rr* dlv_parse(char *name, long ttl, int type, char *s) { - struct rr_dlv *rr = getmem(sizeof(*rr)); - int key_tag, algorithm, digest_type; + struct rr_dlv *rr = getmem(sizeof(*rr)); + int key_tag, algorithm, digest_type; - key_tag = extract_integer(&s, "key tag", NULL); - if (key_tag < 0) return NULL; - rr->key_tag = key_tag; + key_tag = extract_integer(&s, "key tag", NULL); + if (key_tag < 0) return NULL; + rr->key_tag = key_tag; - algorithm = extract_algorithm(&s, "algorithm"); - if (algorithm == ALG_UNSUPPORTED) return NULL; - rr->algorithm = algorithm; + algorithm = extract_algorithm(&s, "algorithm"); + if (algorithm == ALG_UNSUPPORTED) return NULL; + rr->algorithm = algorithm; - digest_type = extract_integer(&s, "digest type", NULL); - if (digest_type < 0) return NULL; - rr->digest_type = digest_type; + digest_type = extract_integer(&s, "digest type", NULL); + if (digest_type < 0) return NULL; + rr->digest_type = digest_type; - rr->digest = extract_hex_binary_data(&s, "digest", EXTRACT_EAT_WHITESPACE); - if (rr->digest.length < 0) return NULL; + rr->digest = extract_hex_binary_data(&s, "digest", EXTRACT_EAT_WHITESPACE); + if (rr->digest.length < 0) return NULL; - switch (digest_type) { - case 1: - if (rr->digest.length != SHA1_BYTES) { - return bitch("wrong SHA-1 digest length: %d bytes found, %d bytes expected", rr->digest.length, SHA1_BYTES); - } - break; - case 2: - if (rr->digest.length != SHA256_BYTES) { - return bitch("wrong SHA-256 digest length: %d bytes found, %d bytes expected", rr->digest.length, SHA256_BYTES); - } - break; - case 3: - if (rr->digest.length != GOST_BYTES) { - return bitch("wrong GOST R 34.11-94 digest length: %d bytes found, %d bytes expected", rr->digest.length, GOST_BYTES); - } - break; - case 4: - if (rr->digest.length != SHA384_BYTES) { - return bitch("wrong SHA-384 digest length: %d bytes found, %d bytes expected", rr->digest.length, SHA384_BYTES); - } - break; - default: - return bitch("bad or unsupported digest type %d", digest_type); - } + switch (digest_type) { + case 1: + if (rr->digest.length != SHA1_BYTES) { + return bitch("wrong SHA-1 digest length: %d bytes found, %d bytes expected", rr->digest.length, SHA1_BYTES); + } + break; + case 2: + if (rr->digest.length != SHA256_BYTES) { + return bitch("wrong SHA-256 digest length: %d bytes found, %d bytes expected", rr->digest.length, SHA256_BYTES); + } + break; + case 3: + if (rr->digest.length != GOST_BYTES) { + return bitch("wrong GOST R 34.11-94 digest length: %d bytes found, %d bytes expected", rr->digest.length, GOST_BYTES); + } + break; + case 4: + if (rr->digest.length != SHA384_BYTES) { + return bitch("wrong SHA-384 digest length: %d bytes found, %d bytes expected", rr->digest.length, SHA384_BYTES); + } + break; + default: + return bitch("bad or unsupported digest type %d", digest_type); + } - if (*s) { - return bitch("garbage after valid DLV data"); - } - G.dnssec_active = 1; - return store_record(type, name, ttl, rr); + if (*s) { + return bitch("garbage after valid DLV data"); + } + G.dnssec_active = 1; + return store_record(type, name, ttl, rr); } static char* dlv_human(struct rr *rrv) { - RRCAST(dlv); + RRCAST(dlv); char ss[4096]; - char *s = ss; - int l; - int i; + char *s = ss; + int l; + int i; l = snprintf(s, 4096, "%u %u %u ", rr->key_tag, rr->algorithm, rr->digest_type); - s += l; - for (i = 0; i < rr->digest.length; i++) { - l = snprintf(s, 4096-(s-ss), "%02X", (unsigned char)rr->digest.data[i]); - s += l; - } + s += l; + for (i = 0; i < rr->digest.length; i++) { + l = snprintf(s, 4096-(s-ss), "%02X", (unsigned char)rr->digest.data[i]); + s += l; + } return quickstrdup_temp(ss); } static struct binary_data dlv_wirerdata(struct rr *rrv) { - RRCAST(dlv); + RRCAST(dlv); - return compose_binary_data("211d", 1, - rr->key_tag, rr->algorithm, rr->digest_type, - rr->digest); + return compose_binary_data("211d", 1, + rr->key_tag, rr->algorithm, rr->digest_type, + rr->digest); } struct rr_methods dlv_methods = { dlv_parse, dlv_human, dlv_wirerdata, NULL, NULL }; diff --git a/dname.c b/dname.c index 6d384ff..9d246bd 100644 --- a/dname.c +++ b/dname.c @@ -21,66 +21,66 @@ static struct rr *dname_parse(char *name, long ttl, int type, char *s) { - struct rr_dname *rr = getmem(sizeof(*rr)); + struct rr_dname *rr = getmem(sizeof(*rr)); - rr->target = extract_name(&s, "dname target", 0); - if (!rr->target) - return NULL; - if (*s) { - return bitch("garbage after valid DNAME data"); - } + rr->target = extract_name(&s, "dname target", 0); + if (!rr->target) + return NULL; + if (*s) { + return bitch("garbage after valid DNAME data"); + } - return store_record(type, name, ttl, rr); + return store_record(type, name, ttl, rr); } static char* dname_human(struct rr *rrv) { - RRCAST(dname); + RRCAST(dname); return rr->target; } static struct binary_data dname_wirerdata(struct rr *rrv) { - RRCAST(dname); - return name2wire_name(rr->target); + RRCAST(dname); + return name2wire_name(rr->target); } static void* dname_validate_set(struct rr_set *rr_set) { - struct rr *rr; - struct rr_set *suspect; - int count; - struct named_rr *named_rr, *next_named_rr; + struct rr *rr; + struct rr_set *suspect; + int count; + struct named_rr *named_rr, *next_named_rr; - if (G.opt.policy_checks[POLICY_DNAME]) { - named_rr = rr_set->named_rr; - rr = rr_set->tail; - if (rr_set->count > 1) - return moan(rr->file_name, rr->line, "multiple DNAMEs"); - /* This check is already handled by "CNAME and other data" in cname.c * - another_set = find_rr_set_in_named_rr(named_rr, T_CNAME); - if (another_set) - return moan(rr->file_name, rr->line, "DNAME cannot co-exist with a CNAME"); - */ - next_named_rr = find_next_named_rr(named_rr); - /* handle http://tools.ietf.org/html/rfc5155#section-10.2 case */ - if (next_named_rr && next_named_rr->parent == named_rr && (named_rr->flags & NAME_FLAG_APEX)) { - count = get_rr_set_count(next_named_rr); - if (count > 0) { - suspect = find_rr_set_in_named_rr(next_named_rr, T_RRSIG); - if (suspect) count--; - suspect = find_rr_set_in_named_rr(next_named_rr, T_NSEC3); - if (suspect) count--; - if (count == 0) - next_named_rr = find_next_named_rr(next_named_rr); - } - } - if (next_named_rr && next_named_rr->parent == named_rr) - return moan(rr->file_name, rr->line, - "DNAME must not have any children (but %s exists)", - next_named_rr->name); - } - return NULL; + if (G.opt.policy_checks[POLICY_DNAME]) { + named_rr = rr_set->named_rr; + rr = rr_set->tail; + if (rr_set->count > 1) + return moan(rr->file_name, rr->line, "multiple DNAMEs"); + /* This check is already handled by "CNAME and other data" in cname.c * + another_set = find_rr_set_in_named_rr(named_rr, T_CNAME); + if (another_set) + return moan(rr->file_name, rr->line, "DNAME cannot co-exist with a CNAME"); + */ + next_named_rr = find_next_named_rr(named_rr); + /* handle http://tools.ietf.org/html/rfc5155#section-10.2 case */ + if (next_named_rr && next_named_rr->parent == named_rr && (named_rr->flags & NAME_FLAG_APEX)) { + count = get_rr_set_count(next_named_rr); + if (count > 0) { + suspect = find_rr_set_in_named_rr(next_named_rr, T_RRSIG); + if (suspect) count--; + suspect = find_rr_set_in_named_rr(next_named_rr, T_NSEC3); + if (suspect) count--; + if (count == 0) + next_named_rr = find_next_named_rr(next_named_rr); + } + } + if (next_named_rr && next_named_rr->parent == named_rr) + return moan(rr->file_name, rr->line, + "DNAME must not have any children (but %s exists)", + next_named_rr->name); + } + return NULL; } struct rr_methods dname_methods = { dname_parse, dname_human, dname_wirerdata, dname_validate_set, NULL }; diff --git a/dnskey.c b/dnskey.c index 503248b..206ce07 100644 --- a/dnskey.c +++ b/dnskey.c @@ -26,232 +26,232 @@ static struct rr_dnskey *all_dns_keys = NULL; static struct rr* dnskey_parse(char *name, long ttl, int type, char *s) { - struct rr_dnskey *rr = getmem(sizeof(*rr)); - struct binary_data key; - int flags, proto, algorithm; - unsigned int ac; - int i; - static struct rr *result; - - flags = extract_integer(&s, "flags", NULL); - if (flags < 0) return NULL; - if (flags & 0xfe7e) - return bitch("reserved flags bits are set"); - if (flags & 0x0001 && !(flags & 0x0100)) - return bitch("SEP bit is set but Zone Key bit is unset"); - rr->flags = flags; - - /* TODO validate that `name` is the name of the zone if flags have Zone Key bit set */ - - proto = extract_integer(&s, "protocol", NULL); - if (proto < 0) return NULL; - if (proto != 3) - return bitch("bad protocol value"); - rr->protocol = proto; - - algorithm = extract_algorithm(&s, "algorithm"); - if (algorithm == ALG_UNSUPPORTED) return NULL; - if (algorithm == ALG_PRIVATEDNS || algorithm == ALG_PRIVATEOID) { - return bitch("private algorithms are not supported in DNSKEY"); - } - rr->algorithm = algorithm; - - key = extract_base64_binary_data(&s, "public key"); - if (key.length < 0) return NULL; - /* TODO validate key length based on algorithm */ - rr->pubkey = key; - - ac = 0; - ac += rr->flags; - ac += rr->protocol << 8; - ac += rr->algorithm; - for (i = 0; i < rr->pubkey.length; i++) { - ac += (i & 1) ? (unsigned char)rr->pubkey.data[i] : ((unsigned char)rr->pubkey.data[i]) << 8; - } - ac += (ac >> 16) & 0xFFFF; - rr->key_tag = ac & 0xFFFF; - - rr->pkey_built = 0; - rr->pkey = NULL; - rr->key_type = KEY_TYPE_UNUSED; - - if (*s) { - return bitch("garbage after valid DNSKEY data"); - } - result = store_record(type, name, ttl, rr); - if (result) { - rr->next_key = all_dns_keys; - all_dns_keys = rr; - } - return result; + struct rr_dnskey *rr = getmem(sizeof(*rr)); + struct binary_data key; + int flags, proto, algorithm; + unsigned int ac; + int i; + static struct rr *result; + + flags = extract_integer(&s, "flags", NULL); + if (flags < 0) return NULL; + if (flags & 0xfe7e) + return bitch("reserved flags bits are set"); + if (flags & 0x0001 && !(flags & 0x0100)) + return bitch("SEP bit is set but Zone Key bit is unset"); + rr->flags = flags; + + /* TODO validate that `name` is the name of the zone if flags have Zone Key bit set */ + + proto = extract_integer(&s, "protocol", NULL); + if (proto < 0) return NULL; + if (proto != 3) + return bitch("bad protocol value"); + rr->protocol = proto; + + algorithm = extract_algorithm(&s, "algorithm"); + if (algorithm == ALG_UNSUPPORTED) return NULL; + if (algorithm == ALG_PRIVATEDNS || algorithm == ALG_PRIVATEOID) { + return bitch("private algorithms are not supported in DNSKEY"); + } + rr->algorithm = algorithm; + + key = extract_base64_binary_data(&s, "public key"); + if (key.length < 0) return NULL; + /* TODO validate key length based on algorithm */ + rr->pubkey = key; + + ac = 0; + ac += rr->flags; + ac += rr->protocol << 8; + ac += rr->algorithm; + for (i = 0; i < rr->pubkey.length; i++) { + ac += (i & 1) ? (unsigned char)rr->pubkey.data[i] : ((unsigned char)rr->pubkey.data[i]) << 8; + } + ac += (ac >> 16) & 0xFFFF; + rr->key_tag = ac & 0xFFFF; + + rr->pkey_built = 0; + rr->pkey = NULL; + rr->key_type = KEY_TYPE_UNUSED; + + if (*s) { + return bitch("garbage after valid DNSKEY data"); + } + result = store_record(type, name, ttl, rr); + if (result) { + rr->next_key = all_dns_keys; + all_dns_keys = rr; + } + return result; } static char* dnskey_human(struct rr *rrv) { - RRCAST(dnskey); + RRCAST(dnskey); char s[1024]; snprintf(s, 1024, "%hu %d %d XXX ; key id = %hu", - rr->flags, rr->protocol, rr->algorithm, rr->key_tag); + rr->flags, rr->protocol, rr->algorithm, rr->key_tag); return quickstrdup_temp(s); } static struct binary_data dnskey_wirerdata(struct rr *rrv) { - RRCAST(dnskey); + RRCAST(dnskey); - return compose_binary_data("211d", 1, - rr->flags, rr->protocol, rr->algorithm, - rr->pubkey); + return compose_binary_data("211d", 1, + rr->flags, rr->protocol, rr->algorithm, + rr->pubkey); } static void *dnskey_validate(struct rr *rrv) { - RRCAST(dnskey); - - if (G.opt.policy_checks[POLICY_DNSKEY]) { - if (algorithm_type(rr->algorithm) == ALG_RSA_FAMILY) { - unsigned int e_bytes; - unsigned char *pk; - int l; - - pk = (unsigned char *)rr->pubkey.data; - l = rr->pubkey.length; - - e_bytes = *pk++; - l--; - if (e_bytes == 0) { - if (l < 2) - return moan(rr->rr.file_name, rr->rr.line, "public key is too short"); - e_bytes = (*pk++) << 8; - e_bytes += *pk++; - l -= 2; - } - if (l < e_bytes) - return moan(rr->rr.file_name, rr->rr.line, "public key is too short"); - - if (*pk == 0) - return moan(rr->rr.file_name, rr->rr.line, "leading zero octets in public key exponent"); - pk += e_bytes; - l -= e_bytes; - if (l > 0 && *pk == 0) - return moan(rr->rr.file_name, rr->rr.line, "leading zero octets in key modulus"); - } - } - return NULL; + RRCAST(dnskey); + + if (G.opt.policy_checks[POLICY_DNSKEY]) { + if (algorithm_type(rr->algorithm) == ALG_RSA_FAMILY) { + unsigned int e_bytes; + unsigned char *pk; + int l; + + pk = (unsigned char *)rr->pubkey.data; + l = rr->pubkey.length; + + e_bytes = *pk++; + l--; + if (e_bytes == 0) { + if (l < 2) + return moan(rr->rr.file_name, rr->rr.line, "public key is too short"); + e_bytes = (*pk++) << 8; + e_bytes += *pk++; + l -= 2; + } + if (l < e_bytes) + return moan(rr->rr.file_name, rr->rr.line, "public key is too short"); + + if (*pk == 0) + return moan(rr->rr.file_name, rr->rr.line, "leading zero octets in public key exponent"); + pk += e_bytes; + l -= e_bytes; + if (l > 0 && *pk == 0) + return moan(rr->rr.file_name, rr->rr.line, "leading zero octets in key modulus"); + } + } + return NULL; } struct rr_methods dnskey_methods = { dnskey_parse, dnskey_human, dnskey_wirerdata, NULL, dnskey_validate }; int dnskey_build_pkey(struct rr_dnskey *rr) { - if (rr->pkey_built) - return rr->pkey ? 1 : 0; - - rr->pkey_built = 1; - - if (algorithm_type(rr->algorithm) == ALG_RSA_FAMILY) { - RSA *rsa; - EVP_PKEY *pkey; - unsigned int e_bytes; - unsigned char *pk; - int l; - - rsa = RSA_new(); - if (!rsa) - goto done; - - pk = (unsigned char *)rr->pubkey.data; - l = rr->pubkey.length; - - e_bytes = *pk++; - l--; - if (e_bytes == 0) { - if (l < 2) /* public key is too short */ - goto done; - e_bytes = (*pk++) << 8; - e_bytes += *pk++; - l -= 2; - } - if (l < e_bytes) /* public key is too short */ - goto done; - - rsa->e = BN_bin2bn(pk, e_bytes, NULL); - pk += e_bytes; - l -= e_bytes; - - rsa->n = BN_bin2bn(pk, l, NULL); - - pkey = EVP_PKEY_new(); - if (!pkey) - goto done; - - if (!EVP_PKEY_set1_RSA(pkey, rsa)) - goto done; - - rr->pkey = pkey; - } else if (algorithm_type(rr->algorithm) == ALG_ECC_FAMILY) { - EC_KEY *pubeckey; - EVP_PKEY *pkey; - unsigned char *pk; - int l; - BIGNUM *bn_x = NULL; - BIGNUM *bn_y = NULL; - - if (rr->algorithm == ALG_ECDSAP256SHA256) { - l = SHA256_DIGEST_LENGTH; - pubeckey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); - } else if (rr->algorithm == ALG_ECDSAP384SHA384) { - l = SHA384_DIGEST_LENGTH; - pubeckey = EC_KEY_new_by_curve_name(NID_secp384r1); - } else { - goto done; - } - - if (!pubeckey) - goto done; - - if (rr->pubkey.length != 2*l) { - goto done; - } - - pk = (unsigned char *)rr->pubkey.data; - - bn_x = BN_bin2bn(pk, l, NULL); - bn_y = BN_bin2bn(&pk[l], l, NULL); - - if (1 != EC_KEY_set_public_key_affine_coordinates(pubeckey, bn_x, bn_y)) { - goto done; - } - - pkey = EVP_PKEY_new(); - if (!pkey) - goto done; - - if (!EVP_PKEY_assign_EC_KEY(pkey, pubeckey)) - goto done; - - rr->pkey = pkey; - } + if (rr->pkey_built) + return rr->pkey ? 1 : 0; + + rr->pkey_built = 1; + + if (algorithm_type(rr->algorithm) == ALG_RSA_FAMILY) { + RSA *rsa; + EVP_PKEY *pkey; + unsigned int e_bytes; + unsigned char *pk; + int l; + + rsa = RSA_new(); + if (!rsa) + goto done; + + pk = (unsigned char *)rr->pubkey.data; + l = rr->pubkey.length; + + e_bytes = *pk++; + l--; + if (e_bytes == 0) { + if (l < 2) /* public key is too short */ + goto done; + e_bytes = (*pk++) << 8; + e_bytes += *pk++; + l -= 2; + } + if (l < e_bytes) /* public key is too short */ + goto done; + + rsa->e = BN_bin2bn(pk, e_bytes, NULL); + pk += e_bytes; + l -= e_bytes; + + rsa->n = BN_bin2bn(pk, l, NULL); + + pkey = EVP_PKEY_new(); + if (!pkey) + goto done; + + if (!EVP_PKEY_set1_RSA(pkey, rsa)) + goto done; + + rr->pkey = pkey; + } else if (algorithm_type(rr->algorithm) == ALG_ECC_FAMILY) { + EC_KEY *pubeckey; + EVP_PKEY *pkey; + unsigned char *pk; + int l; + BIGNUM *bn_x = NULL; + BIGNUM *bn_y = NULL; + + if (rr->algorithm == ALG_ECDSAP256SHA256) { + l = SHA256_DIGEST_LENGTH; + pubeckey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + } else if (rr->algorithm == ALG_ECDSAP384SHA384) { + l = SHA384_DIGEST_LENGTH; + pubeckey = EC_KEY_new_by_curve_name(NID_secp384r1); + } else { + goto done; + } + + if (!pubeckey) + goto done; + + if (rr->pubkey.length != 2*l) { + goto done; + } + + pk = (unsigned char *)rr->pubkey.data; + + bn_x = BN_bin2bn(pk, l, NULL); + bn_y = BN_bin2bn(&pk[l], l, NULL); + + if (1 != EC_KEY_set_public_key_affine_coordinates(pubeckey, bn_x, bn_y)) { + goto done; + } + + pkey = EVP_PKEY_new(); + if (!pkey) + goto done; + + if (!EVP_PKEY_assign_EC_KEY(pkey, pubeckey)) + goto done; + + rr->pkey = pkey; + } done: - if (!rr->pkey) { - moan(rr->rr.file_name, rr->rr.line, "error building pkey"); - } - return rr->pkey ? 1 : 0; + if (!rr->pkey) { + moan(rr->rr.file_name, rr->rr.line, "error building pkey"); + } + return rr->pkey ? 1 : 0; } void dnskey_ksk_policy_check(void) { - struct rr_dnskey *rr = all_dns_keys; - int ksk_found = 0; - - while (rr) { - if (rr->key_type == KEY_TYPE_KSK) - ksk_found = 1; - rr = rr->next_key; - } - if (!ksk_found) - moan(all_dns_keys->rr.file_name, all_dns_keys->rr.line, "No KSK found"); + struct rr_dnskey *rr = all_dns_keys; + int ksk_found = 0; + + while (rr) { + if (rr->key_type == KEY_TYPE_KSK) + ksk_found = 1; + rr = rr->next_key; + } + if (!ksk_found) + moan(all_dns_keys->rr.file_name, all_dns_keys->rr.line, "No KSK found"); } diff --git a/ds.c b/ds.c index 947f929..25a4442 100644 --- a/ds.c +++ b/ds.c @@ -19,81 +19,81 @@ static struct rr* ds_parse(char *name, long ttl, int type, char *s) { - struct rr_ds *rr = getmem(sizeof(*rr)); - int key_tag, algorithm, digest_type; + struct rr_ds *rr = getmem(sizeof(*rr)); + int key_tag, algorithm, digest_type; - key_tag = extract_integer(&s, "key tag", NULL); - if (key_tag < 0) return NULL; - rr->key_tag = key_tag; + key_tag = extract_integer(&s, "key tag", NULL); + if (key_tag < 0) return NULL; + rr->key_tag = key_tag; - algorithm = extract_algorithm(&s, "algorithm"); - if (algorithm == ALG_UNSUPPORTED) return NULL; - rr->algorithm = algorithm; + algorithm = extract_algorithm(&s, "algorithm"); + if (algorithm == ALG_UNSUPPORTED) return NULL; + rr->algorithm = algorithm; - digest_type = extract_integer(&s, "digest type", NULL); - if (digest_type < 0) return NULL; - rr->digest_type = digest_type; + digest_type = extract_integer(&s, "digest type", NULL); + if (digest_type < 0) return NULL; + rr->digest_type = digest_type; - rr->digest = extract_hex_binary_data(&s, "digest", EXTRACT_EAT_WHITESPACE); - if (rr->digest.length < 0) return NULL; + rr->digest = extract_hex_binary_data(&s, "digest", EXTRACT_EAT_WHITESPACE); + if (rr->digest.length < 0) return NULL; - /* See http://www.iana.org/assignments/ds-rr-types/ds-rr-types.xml - * for valid digest types. */ - switch (digest_type) { - case 1: - if (rr->digest.length != SHA1_BYTES) { - return bitch("wrong SHA-1 digest length: %d bytes found, %d bytes expected", rr->digest.length, SHA1_BYTES); - } - break; - case 2: - if (rr->digest.length != SHA256_BYTES) { - return bitch("wrong SHA-256 digest length: %d bytes found, %d bytes expected", rr->digest.length, SHA256_BYTES); - } - break; - case 3: - if (rr->digest.length != GOST_BYTES) { - return bitch("wrong GOST R 34.11-94 digest length: %d bytes found, %d bytes expected", rr->digest.length, GOST_BYTES); - } - break; - case 4: - if (rr->digest.length != SHA384_BYTES) { - return bitch("wrong SHA-384 digest length: %d bytes found, %d bytes expected", rr->digest.length, SHA384_BYTES); - } - break; - default: - return bitch("bad or unsupported digest type %d", digest_type); - } + /* See http://www.iana.org/assignments/ds-rr-types/ds-rr-types.xml + * for valid digest types. */ + switch (digest_type) { + case 1: + if (rr->digest.length != SHA1_BYTES) { + return bitch("wrong SHA-1 digest length: %d bytes found, %d bytes expected", rr->digest.length, SHA1_BYTES); + } + break; + case 2: + if (rr->digest.length != SHA256_BYTES) { + return bitch("wrong SHA-256 digest length: %d bytes found, %d bytes expected", rr->digest.length, SHA256_BYTES); + } + break; + case 3: + if (rr->digest.length != GOST_BYTES) { + return bitch("wrong GOST R 34.11-94 digest length: %d bytes found, %d bytes expected", rr->digest.length, GOST_BYTES); + } + break; + case 4: + if (rr->digest.length != SHA384_BYTES) { + return bitch("wrong SHA-384 digest length: %d bytes found, %d bytes expected", rr->digest.length, SHA384_BYTES); + } + break; + default: + return bitch("bad or unsupported digest type %d", digest_type); + } - if (*s) { - return bitch("garbage after valid DS data"); - } - return store_record(type, name, ttl, rr); + if (*s) { + return bitch("garbage after valid DS data"); + } + return store_record(type, name, ttl, rr); } static char* ds_human(struct rr *rrv) { - RRCAST(ds); + RRCAST(ds); char ss[4096]; - char *s = ss; - int l; - int i; + char *s = ss; + int l; + int i; l = snprintf(s, 4096, "%u %u %u ", rr->key_tag, rr->algorithm, rr->digest_type); - s += l; - for (i = 0; i < rr->digest.length; i++) { - l = snprintf(s, 4096-(s-ss), "%02X", (unsigned char)rr->digest.data[i]); - s += l; - } + s += l; + for (i = 0; i < rr->digest.length; i++) { + l = snprintf(s, 4096-(s-ss), "%02X", (unsigned char)rr->digest.data[i]); + s += l; + } return quickstrdup_temp(ss); } static struct binary_data ds_wirerdata(struct rr *rrv) { - RRCAST(ds); + RRCAST(ds); - return compose_binary_data("211d", 1, - rr->key_tag, rr->algorithm, rr->digest_type, - rr->digest); + return compose_binary_data("211d", 1, + rr->key_tag, rr->algorithm, rr->digest_type, + rr->digest); } struct rr_methods ds_methods = { ds_parse, ds_human, ds_wirerdata, NULL, NULL }; diff --git a/hinfo.c b/hinfo.c index cac85c5..f353c50 100644 --- a/hinfo.c +++ b/hinfo.c @@ -20,30 +20,30 @@ static struct rr *hinfo_parse(char *name, long ttl, int type, char *s) { - struct rr_hinfo *rr = getmem(sizeof(*rr)); + struct rr_hinfo *rr = getmem(sizeof(*rr)); - rr->cpu = extract_text(&s, "CPU"); - if (rr->cpu.length < 0) - return NULL; - if (rr->cpu.length > 255) - return bitch("CPU string is too long"); + rr->cpu = extract_text(&s, "CPU"); + if (rr->cpu.length < 0) + return NULL; + if (rr->cpu.length > 255) + return bitch("CPU string is too long"); - rr->os = extract_text(&s, "OS"); - if (rr->os.length < 0) - return NULL; - if (rr->os.length > 255) - return bitch("OS string is too long"); + rr->os = extract_text(&s, "OS"); + if (rr->os.length < 0) + return NULL; + if (rr->os.length > 255) + return bitch("OS string is too long"); - if (*s) { - return bitch("garbage after valid HINFO data"); - } + if (*s) { + return bitch("garbage after valid HINFO data"); + } - return store_record(type, name, ttl, rr); + return store_record(type, name, ttl, rr); } static char* hinfo_human(struct rr *rrv) { - RRCAST(hinfo); + RRCAST(hinfo); char s[1024]; snprintf(s, 1024, "\"%s\" \"%s\"", rr->cpu.data, rr->os.data); @@ -52,7 +52,7 @@ static char* hinfo_human(struct rr *rrv) static struct binary_data hinfo_wirerdata(struct rr *rrv) { - RRCAST(hinfo); + RRCAST(hinfo); return compose_binary_data("bb", 1, rr->cpu, rr->os); } diff --git a/ipseckey.c b/ipseckey.c index c5bdf94..6c7f752 100644 --- a/ipseckey.c +++ b/ipseckey.c @@ -21,157 +21,157 @@ static struct rr *ipseckey_parse(char *name, long ttl, int type, char *s) { - struct rr_ipseckey *rr = getmem(sizeof(*rr)); - int i; - - rr->precedence = i = extract_integer(&s, "precedence", NULL); - if (i < 0) return NULL; - if (i >= 256) return bitch("precedence range is not valid"); - - rr->gateway_type = i = extract_integer(&s, "gateway type", NULL); - if (i < 0) return NULL; - if (i > 3) return bitch("gateway type is not valid"); - - rr->algorithm = i = extract_integer(&s, "algorithm", NULL); - if (i < 0) return NULL; - if (i > 2) return bitch("algorithm is not valid"); - - switch (rr->gateway_type) { - case 0: - rr->gateway.gateway_none = extract_name(&s, "gateway/.", KEEP_CAPITALIZATION); - if (!rr->gateway.gateway_none) return NULL; - if (strcmp(rr->gateway.gateway_none, ".") != 0) - return bitch("gateway must be \".\" for gateway type 0"); - break; - case 1: - if (extract_ipv4(&s, "gateway/IPv4", &rr->gateway.gateway_ipv4) <= 0) - return NULL; - break; - case 2: - if (extract_ipv6(&s, "gateway/IPv6", &rr->gateway.gateway_ipv6) <= 0) - return NULL; - break; - case 3: - rr->gateway.gateway_name = extract_name(&s, "gateway/name", KEEP_CAPITALIZATION); - if (!rr->gateway.gateway_name) return NULL; - break; - default: - croakx(7, "assertion failed: gateway type %d not within range", rr->gateway_type); - } - - /* My reading of http://tools.ietf.org/html/rfc4025 is fuzzy on: - * - * - whether it is possible to have algorithm 0 and non-empty key; - * - whether it is possible to have empty key and algorithm != 0. - * - * Here I assume "not possible" for both. - */ - switch (rr->algorithm) { - case 0: - break; - case 1: - /* DSA key */ - rr->public_key = extract_base64_binary_data(&s, "public key"); - if (rr->public_key.length < 0) return NULL; - break; - case 2: - /* RSA key */ - rr->public_key = extract_base64_binary_data(&s, "public key"); - if (rr->public_key.length < 0) return NULL; - break; - default: - croakx(7, "assertion failed: algorithm %d not within range", rr->algorithm); - } - - if (*s) { - return bitch("garbage after valid IPSECKEY data"); - } - - return store_record(type, name, ttl, rr); + struct rr_ipseckey *rr = getmem(sizeof(*rr)); + int i; + + rr->precedence = i = extract_integer(&s, "precedence", NULL); + if (i < 0) return NULL; + if (i >= 256) return bitch("precedence range is not valid"); + + rr->gateway_type = i = extract_integer(&s, "gateway type", NULL); + if (i < 0) return NULL; + if (i > 3) return bitch("gateway type is not valid"); + + rr->algorithm = i = extract_integer(&s, "algorithm", NULL); + if (i < 0) return NULL; + if (i > 2) return bitch("algorithm is not valid"); + + switch (rr->gateway_type) { + case 0: + rr->gateway.gateway_none = extract_name(&s, "gateway/.", KEEP_CAPITALIZATION); + if (!rr->gateway.gateway_none) return NULL; + if (strcmp(rr->gateway.gateway_none, ".") != 0) + return bitch("gateway must be \".\" for gateway type 0"); + break; + case 1: + if (extract_ipv4(&s, "gateway/IPv4", &rr->gateway.gateway_ipv4) <= 0) + return NULL; + break; + case 2: + if (extract_ipv6(&s, "gateway/IPv6", &rr->gateway.gateway_ipv6) <= 0) + return NULL; + break; + case 3: + rr->gateway.gateway_name = extract_name(&s, "gateway/name", KEEP_CAPITALIZATION); + if (!rr->gateway.gateway_name) return NULL; + break; + default: + croakx(7, "assertion failed: gateway type %d not within range", rr->gateway_type); + } + + /* My reading of http://tools.ietf.org/html/rfc4025 is fuzzy on: + * + * - whether it is possible to have algorithm 0 and non-empty key; + * - whether it is possible to have empty key and algorithm != 0. + * + * Here I assume "not possible" for both. + */ + switch (rr->algorithm) { + case 0: + break; + case 1: + /* DSA key */ + rr->public_key = extract_base64_binary_data(&s, "public key"); + if (rr->public_key.length < 0) return NULL; + break; + case 2: + /* RSA key */ + rr->public_key = extract_base64_binary_data(&s, "public key"); + if (rr->public_key.length < 0) return NULL; + break; + default: + croakx(7, "assertion failed: algorithm %d not within range", rr->algorithm); + } + + if (*s) { + return bitch("garbage after valid IPSECKEY data"); + } + + return store_record(type, name, ttl, rr); } static char* ipseckey_human(struct rr *rrv) { - RRCAST(ipseckey); + RRCAST(ipseckey); char s[1024], gw[1024]; - switch (rr->gateway_type) { - case 0: - strcpy(gw, rr->gateway.gateway_none); - break; - case 1: - inet_ntop(AF_INET, &rr->gateway.gateway_ipv4, gw, 1024); - break; - case 2: - inet_ntop(AF_INET6, &rr->gateway.gateway_ipv6, gw, 1024); - break; - case 3: - strcpy(gw, rr->gateway.gateway_name); - break; - default: - strcpy(gw, "??"); - } + switch (rr->gateway_type) { + case 0: + strcpy(gw, rr->gateway.gateway_none); + break; + case 1: + inet_ntop(AF_INET, &rr->gateway.gateway_ipv4, gw, 1024); + break; + case 2: + inet_ntop(AF_INET6, &rr->gateway.gateway_ipv6, gw, 1024); + break; + case 3: + strcpy(gw, rr->gateway.gateway_name); + break; + default: + strcpy(gw, "??"); + } snprintf(s, 1024, "( %d %d %d %s ... )", - rr->precedence, rr->gateway_type, rr->algorithm, gw); + rr->precedence, rr->gateway_type, rr->algorithm, gw); return quickstrdup_temp(s); } static struct binary_data ipseckey_wirerdata(struct rr *rrv) { - RRCAST(ipseckey); - struct binary_data helper; - - switch (rr->gateway_type) { - case 0: - if (rr->algorithm != 0) - return compose_binary_data("111d", 1, - rr->precedence, rr->gateway_type, rr->algorithm, - rr->public_key); - else - return compose_binary_data("111", 1, - rr->precedence, rr->gateway_type, rr->algorithm); - break; - case 1: - helper.length = sizeof(rr->gateway.gateway_ipv4); - helper.data = (void *)&rr->gateway.gateway_ipv4; - - if (rr->algorithm != 0) - return compose_binary_data("111dd", 1, - rr->precedence, rr->gateway_type, rr->algorithm, - helper, - rr->public_key); - else - return compose_binary_data("111d", 1, - rr->precedence, rr->gateway_type, rr->algorithm, - helper); - break; - case 2: - - helper.length = sizeof(rr->gateway.gateway_ipv6); - helper.data = (void *)&rr->gateway.gateway_ipv6; - - if (rr->algorithm != 0) - return compose_binary_data("111dd", 1, - rr->precedence, rr->gateway_type, rr->algorithm, - helper, - rr->public_key); - else - return compose_binary_data("111d", 1, - rr->precedence, rr->gateway_type, rr->algorithm, - helper); - break; - case 3: - if (rr->algorithm != 0) - return compose_binary_data("111dd", 1, - rr->precedence, rr->gateway_type, rr->algorithm, - name2wire_name(rr->gateway.gateway_name), - rr->public_key); - else - return compose_binary_data("111d", 1, - rr->precedence, rr->gateway_type, rr->algorithm, - name2wire_name(rr->gateway.gateway_name)); - break; - } + RRCAST(ipseckey); + struct binary_data helper; + + switch (rr->gateway_type) { + case 0: + if (rr->algorithm != 0) + return compose_binary_data("111d", 1, + rr->precedence, rr->gateway_type, rr->algorithm, + rr->public_key); + else + return compose_binary_data("111", 1, + rr->precedence, rr->gateway_type, rr->algorithm); + break; + case 1: + helper.length = sizeof(rr->gateway.gateway_ipv4); + helper.data = (void *)&rr->gateway.gateway_ipv4; + + if (rr->algorithm != 0) + return compose_binary_data("111dd", 1, + rr->precedence, rr->gateway_type, rr->algorithm, + helper, + rr->public_key); + else + return compose_binary_data("111d", 1, + rr->precedence, rr->gateway_type, rr->algorithm, + helper); + break; + case 2: + + helper.length = sizeof(rr->gateway.gateway_ipv6); + helper.data = (void *)&rr->gateway.gateway_ipv6; + + if (rr->algorithm != 0) + return compose_binary_data("111dd", 1, + rr->precedence, rr->gateway_type, rr->algorithm, + helper, + rr->public_key); + else + return compose_binary_data("111d", 1, + rr->precedence, rr->gateway_type, rr->algorithm, + helper); + break; + case 3: + if (rr->algorithm != 0) + return compose_binary_data("111dd", 1, + rr->precedence, rr->gateway_type, rr->algorithm, + name2wire_name(rr->gateway.gateway_name), + rr->public_key); + else + return compose_binary_data("111d", 1, + rr->precedence, rr->gateway_type, rr->algorithm, + name2wire_name(rr->gateway.gateway_name)); + break; + } return bad_binary_data(); } diff --git a/isdn.c b/isdn.c index 042596d..e9c1821 100644 --- a/isdn.c +++ b/isdn.c @@ -23,52 +23,52 @@ static struct rr *isdn_parse(char *name, long ttl, int type, char *s) { - struct rr_isdn *rr = getmem(sizeof(*rr)); + struct rr_isdn *rr = getmem(sizeof(*rr)); - rr->isdn_address = extract_text(&s, "ISDN-address"); - if (rr->isdn_address.length < 0) - return NULL; - if (rr->isdn_address.length > 255) - return bitch("ISDN-address too long"); + rr->isdn_address = extract_text(&s, "ISDN-address"); + if (rr->isdn_address.length < 0) + return NULL; + if (rr->isdn_address.length > 255) + return bitch("ISDN-address too long"); - rr->sa_present = 0; - if (*s) { - rr->sa = extract_text(&s, "subaddress"); - if (rr->sa.length < 0) - return NULL; - if (rr->sa.length > 255) - return bitch("subaddress too long"); - rr->sa_present = 1; - } + rr->sa_present = 0; + if (*s) { + rr->sa = extract_text(&s, "subaddress"); + if (rr->sa.length < 0) + return NULL; + if (rr->sa.length > 255) + return bitch("subaddress too long"); + rr->sa_present = 1; + } - if (*s) { - return bitch("garbage after valid ISDN data"); - } + if (*s) { + return bitch("garbage after valid ISDN data"); + } - return store_record(type, name, ttl, rr); + return store_record(type, name, ttl, rr); } static char* isdn_human(struct rr *rrv) { - RRCAST(isdn); + RRCAST(isdn); return rr->isdn_address.data; } static struct binary_data isdn_wirerdata(struct rr *rrv) { - RRCAST(isdn); - struct binary_data r, t; + RRCAST(isdn); + struct binary_data r, t; - r = bad_binary_data(); - t.length = 0; - t.data = NULL; - r = compose_binary_data("db", 1, t, rr->isdn_address); - t = r; - if (rr->sa_present) { - r = compose_binary_data("db", 1, t, rr->sa); - t = r; - } + r = bad_binary_data(); + t.length = 0; + t.data = NULL; + r = compose_binary_data("db", 1, t, rr->isdn_address); + t = r; + if (rr->sa_present) { + r = compose_binary_data("db", 1, t, rr->sa); + t = r; + } return r; } diff --git a/kx.c b/kx.c index f69ba1b..8cddfbd 100644 --- a/kx.c +++ b/kx.c @@ -19,40 +19,40 @@ static struct rr *kx_parse(char *name, long ttl, int type, char *s) { - struct rr_kx *rr = getmem(sizeof(*rr)); + struct rr_kx *rr = getmem(sizeof(*rr)); - rr->preference = extract_integer(&s, "KX preference", NULL); - if (rr->preference < 0) - return NULL; + rr->preference = extract_integer(&s, "KX preference", NULL); + if (rr->preference < 0) + return NULL; - rr->exchanger = extract_name(&s, "KX exchanger", 0); - if (!rr->exchanger) - return NULL; + rr->exchanger = extract_name(&s, "KX exchanger", 0); + if (!rr->exchanger) + return NULL; - if (*s) { - return bitch("garbage after valid KX data"); - } + if (*s) { + return bitch("garbage after valid KX data"); + } - return store_record(type, name, ttl, rr); + return store_record(type, name, ttl, rr); } static char* kx_human(struct rr *rrv) { - RRCAST(kx); + RRCAST(kx); char s[1024]; snprintf(s, 1024, "%d %s", - rr->preference, rr->exchanger); + rr->preference, rr->exchanger); return quickstrdup_temp(s); } static struct binary_data kx_wirerdata(struct rr *rrv) { - RRCAST(kx); + RRCAST(kx); return compose_binary_data("2d", 1, - rr->preference, - name2wire_name(rr->exchanger)); + rr->preference, + name2wire_name(rr->exchanger)); } struct rr_methods kx_methods = { kx_parse, kx_human, kx_wirerdata, NULL, NULL }; diff --git a/l32.c b/l32.c index a4cdbd6..8890441 100644 --- a/l32.c +++ b/l32.c @@ -19,41 +19,41 @@ static struct rr *l32_parse(char *name, long ttl, int type, char *s) { - struct rr_l32 *rr = getmem(sizeof(*rr)); - struct in_addr ipv4_like; - int preference; - - rr->preference = preference = extract_integer(&s, "L32 preference", NULL); - if (preference < 0) - return NULL; - if (extract_ipv4(&s, "Locator32", &ipv4_like) <= 0) - return NULL; - rr->locator32 = ipv4_like.s_addr; - - if (*s) { - return bitch("garbage after valid L32 data"); - } - - return store_record(type, name, ttl, rr); + struct rr_l32 *rr = getmem(sizeof(*rr)); + struct in_addr ipv4_like; + int preference; + + rr->preference = preference = extract_integer(&s, "L32 preference", NULL); + if (preference < 0) + return NULL; + if (extract_ipv4(&s, "Locator32", &ipv4_like) <= 0) + return NULL; + rr->locator32 = ipv4_like.s_addr; + + if (*s) { + return bitch("garbage after valid L32 data"); + } + + return store_record(type, name, ttl, rr); } static char* l32_human(struct rr *rrv) { - RRCAST(l32); + RRCAST(l32); char s[1024]; snprintf(s, 1024, "%d %d.%d.%d.%d", - rr->preference, - (rr->locator32 >> 24) & 0xff, - (rr->locator32 >> 16) & 0xff, - (rr->locator32 >> 8) & 0xff, - (rr->locator32 >> 0) & 0xff); + rr->preference, + (rr->locator32 >> 24) & 0xff, + (rr->locator32 >> 16) & 0xff, + (rr->locator32 >> 8) & 0xff, + (rr->locator32 >> 0) & 0xff); return quickstrdup_temp(s); } static struct binary_data l32_wirerdata(struct rr *rrv) { - RRCAST(l32); + RRCAST(l32); return compose_binary_data("24", 1, rr->preference, rr->locator32); } diff --git a/l64.c b/l64.c index 896db54..7c125e1 100644 --- a/l64.c +++ b/l64.c @@ -19,39 +19,39 @@ static struct rr *l64_parse(char *name, long ttl, int type, char *s) { - struct rr_l64 *rr = getmem(sizeof(*rr)); - int preference; + struct rr_l64 *rr = getmem(sizeof(*rr)); + int preference; - rr->preference = preference = extract_integer(&s, "L64 preference", NULL); - if (preference < 0) - return NULL; - if (extract_u64(&s, "Locator64", &rr->locator64) < 0) - return NULL; + rr->preference = preference = extract_integer(&s, "L64 preference", NULL); + if (preference < 0) + return NULL; + if (extract_u64(&s, "Locator64", &rr->locator64) < 0) + return NULL; - if (*s) { - return bitch("garbage after valid L64 data"); - } + if (*s) { + return bitch("garbage after valid L64 data"); + } - return store_record(type, name, ttl, rr); + return store_record(type, name, ttl, rr); } static char* l64_human(struct rr *rrv) { - RRCAST(l64); + RRCAST(l64); char s[1024]; snprintf(s, 1024, "%d %x:%x:%x:%x", - rr->preference, - (unsigned)(rr->locator64 >> 48) & 0xffff, - (unsigned)(rr->locator64 >> 32) & 0xffff, - (unsigned)(rr->locator64 >> 16) & 0xffff, - (unsigned)(rr->locator64 >> 0) & 0xffff); + rr->preference, + (unsigned)(rr->locator64 >> 48) & 0xffff, + (unsigned)(rr->locator64 >> 32) & 0xffff, + (unsigned)(rr->locator64 >> 16) & 0xffff, + (unsigned)(rr->locator64 >> 0) & 0xffff); return quickstrdup_temp(s); } static struct binary_data l64_wirerdata(struct rr *rrv) { - RRCAST(l64); + RRCAST(l64); return compose_binary_data("28", 1, rr->preference, rr->locator64); } diff --git a/loc.c b/loc.c index 81264e5..eb75494 100644 --- a/loc.c +++ b/loc.c @@ -21,161 +21,161 @@ static uint8_t double2loc_format(double val) { - if (val > 1000000000) { - return (((uint8_t)(val / 1000000000)) << 4) | 9; - } else if (val > 100000000) { - return (((uint8_t)(val / 100000000)) << 4) | 8; - } else if (val > 10000000) { - return (((uint8_t)(val / 10000000)) << 4) | 7; - } else if (val > 1000000) { - return (((uint8_t)(val / 1000000)) << 4) | 6; - } else if (val > 100000) { - return (((uint8_t)(val / 100000)) << 4) | 5; - } else if (val > 10000) { - return (((uint8_t)(val / 10000)) << 4) | 4; - } else if (val > 1000) { - return (((uint8_t)(val / 1000)) << 4) | 3; - } else if (val > 100) { - return (((uint8_t)(val / 100)) << 4) | 2; - } else if (val > 10) { - return (((uint8_t)(val / 10)) << 4) | 1; - } else { - return (((uint8_t)(val)) << 4); - } + if (val > 1000000000) { + return (((uint8_t)(val / 1000000000)) << 4) | 9; + } else if (val > 100000000) { + return (((uint8_t)(val / 100000000)) << 4) | 8; + } else if (val > 10000000) { + return (((uint8_t)(val / 10000000)) << 4) | 7; + } else if (val > 1000000) { + return (((uint8_t)(val / 1000000)) << 4) | 6; + } else if (val > 100000) { + return (((uint8_t)(val / 100000)) << 4) | 5; + } else if (val > 10000) { + return (((uint8_t)(val / 10000)) << 4) | 4; + } else if (val > 1000) { + return (((uint8_t)(val / 1000)) << 4) | 3; + } else if (val > 100) { + return (((uint8_t)(val / 100)) << 4) | 2; + } else if (val > 10) { + return (((uint8_t)(val / 10)) << 4) | 1; + } else { + return (((uint8_t)(val)) << 4); + } } static struct rr *loc_parse(char *name, long ttl, int type, char *s) { - struct rr_loc *rr = getmem(sizeof(*rr)); - long long i; - int deg; - int min; - double sec, val; - - rr->version = 0; - - /* latitude block */ - i = extract_integer(&s, "degrees latitude", NULL); - if (i < 0) - return NULL; - if (i > 90) - return bitch("degrees latitude not in the range 0..90"); - deg = i; - min = 0; - sec = 0; - if (isdigit(*s)) { - i = extract_integer(&s, "minutes latitude", NULL); - if (i < 0) - return NULL; - if (i > 59) - return bitch("minutes latitude not in the range 0..59"); - min = i; - - if (isdigit(*s)) { /* restricted floating point, starting with a digit */ - if (extract_double(&s, "seconds latitude", &sec, 0) < 0) - return NULL; - if (sec < 0 || sec > 59.999) - return bitch("seconds latitude not in the range 0..59.999"); - } - } - rr->latitude = sec*1000 + .5 + min*1000*60 + deg*1000*60*60; - if (*s == 'n' || *s == 'N') { - s++; - rr->latitude = 2147483648u + rr->latitude; - } else if (*s == 's' || *s == 'S') { - s++; - rr->latitude = 2147483648u - rr->latitude; - } else { - return bitch("latitude: N or S is expected"); - } - if (*s && !isspace(*s) && *s != ';' && *s != ')') { - return bitch("latitude: N or S is expected"); - } - s = skip_white_space(s); - if (!s) return NULL; - - /* longitude block */ - i = extract_integer(&s, "degrees longitude", NULL); - if (i < 0) - return NULL; - if (i > 180) - return bitch("degrees longitude not in the range 0..90"); - deg = i; - min = 0; - sec = 0; - if (isdigit(*s)) { - i = extract_integer(&s, "minutes longitude", NULL); - if (i < 0) - return NULL; - if (i > 59) - return bitch("minutes longitude not in the range 0..59"); - min = i; - - if (isdigit(*s)) { /* restricted floating point, starting with a digit */ - if (extract_double(&s, "seconds longitude", &sec, 0) < 0) - return NULL; - if (sec < 0 || sec > 59.999) - return bitch("seconds longitude not in the range 0..59.999"); - } - } - rr->longitude = sec*1000 + .5 + min*1000*60 + deg*1000*60*60; - if (*s == 'e' || *s == 'E') { - s++; - rr->longitude = 2147483648u + rr->longitude; - } else if (*s == 'w' || *s == 'W') { - s++; - rr->longitude = 2147483648u - rr->longitude; - } else { - return bitch("longitude: E or W is expected"); - } - if (*s && !isspace(*s) && *s != ';' && *s != ')') { - return bitch("longitude: E or W is expected"); - } - s = skip_white_space(s); - if (!s) return NULL; - - if (extract_double(&s, "altitude", &val, 1) < 0) - return NULL; - if (val < -100000.00 || val > 42849672.95) - return bitch("altitude is out of supported range"); - rr->altitude = (val + 100000.00) * 100 + 0.5; - - if (*s) { - if (extract_double(&s, "sphere size", &val, 1) < 0) - return NULL; - if (val < 0 || val > 90000000.00) - return bitch("sphere size is out of supported range"); - rr->size = double2loc_format(val * 100 + 0.5); - - if (*s) { - if (extract_double(&s, "horizontal precision", &val, 1) < 0) - return NULL; - if (val < 0 || val > 90000000.00) - return bitch("horizontal precision is out of supported range"); - rr->horiz_pre = double2loc_format(val * 100 + 0.5); - - if (*s) { - if (extract_double(&s, "vertical precision", &val, 1) < 0) - return NULL; - if (val < 0 || val > 90000000.00) - return bitch("vertical precision is out of supported range"); - rr->vert_pre = double2loc_format(val * 100 + 0.5); - } else { - rr->vert_pre = double2loc_format(10 * 100 + 0.5); - } - } else { - rr->horiz_pre = double2loc_format(10000 * 100 + 0.5); - } - } else { - rr->size = double2loc_format(1 * 100 + 0.5); - } - - if (*s) { - return bitch("garbage after valid LOC data"); - } - - return store_record(type, name, ttl, rr); + struct rr_loc *rr = getmem(sizeof(*rr)); + long long i; + int deg; + int min; + double sec, val; + + rr->version = 0; + + /* latitude block */ + i = extract_integer(&s, "degrees latitude", NULL); + if (i < 0) + return NULL; + if (i > 90) + return bitch("degrees latitude not in the range 0..90"); + deg = i; + min = 0; + sec = 0; + if (isdigit(*s)) { + i = extract_integer(&s, "minutes latitude", NULL); + if (i < 0) + return NULL; + if (i > 59) + return bitch("minutes latitude not in the range 0..59"); + min = i; + + if (isdigit(*s)) { /* restricted floating point, starting with a digit */ + if (extract_double(&s, "seconds latitude", &sec, 0) < 0) + return NULL; + if (sec < 0 || sec > 59.999) + return bitch("seconds latitude not in the range 0..59.999"); + } + } + rr->latitude = sec*1000 + .5 + min*1000*60 + deg*1000*60*60; + if (*s == 'n' || *s == 'N') { + s++; + rr->latitude = 2147483648u + rr->latitude; + } else if (*s == 's' || *s == 'S') { + s++; + rr->latitude = 2147483648u - rr->latitude; + } else { + return bitch("latitude: N or S is expected"); + } + if (*s && !isspace(*s) && *s != ';' && *s != ')') { + return bitch("latitude: N or S is expected"); + } + s = skip_white_space(s); + if (!s) return NULL; + + /* longitude block */ + i = extract_integer(&s, "degrees longitude", NULL); + if (i < 0) + return NULL; + if (i > 180) + return bitch("degrees longitude not in the range 0..90"); + deg = i; + min = 0; + sec = 0; + if (isdigit(*s)) { + i = extract_integer(&s, "minutes longitude", NULL); + if (i < 0) + return NULL; + if (i > 59) + return bitch("minutes longitude not in the range 0..59"); + min = i; + + if (isdigit(*s)) { /* restricted floating point, starting with a digit */ + if (extract_double(&s, "seconds longitude", &sec, 0) < 0) + return NULL; + if (sec < 0 || sec > 59.999) + return bitch("seconds longitude not in the range 0..59.999"); + } + } + rr->longitude = sec*1000 + .5 + min*1000*60 + deg*1000*60*60; + if (*s == 'e' || *s == 'E') { + s++; + rr->longitude = 2147483648u + rr->longitude; + } else if (*s == 'w' || *s == 'W') { + s++; + rr->longitude = 2147483648u - rr->longitude; + } else { + return bitch("longitude: E or W is expected"); + } + if (*s && !isspace(*s) && *s != ';' && *s != ')') { + return bitch("longitude: E or W is expected"); + } + s = skip_white_space(s); + if (!s) return NULL; + + if (extract_double(&s, "altitude", &val, 1) < 0) + return NULL; + if (val < -100000.00 || val > 42849672.95) + return bitch("altitude is out of supported range"); + rr->altitude = (val + 100000.00) * 100 + 0.5; + + if (*s) { + if (extract_double(&s, "sphere size", &val, 1) < 0) + return NULL; + if (val < 0 || val > 90000000.00) + return bitch("sphere size is out of supported range"); + rr->size = double2loc_format(val * 100 + 0.5); + + if (*s) { + if (extract_double(&s, "horizontal precision", &val, 1) < 0) + return NULL; + if (val < 0 || val > 90000000.00) + return bitch("horizontal precision is out of supported range"); + rr->horiz_pre = double2loc_format(val * 100 + 0.5); + + if (*s) { + if (extract_double(&s, "vertical precision", &val, 1) < 0) + return NULL; + if (val < 0 || val > 90000000.00) + return bitch("vertical precision is out of supported range"); + rr->vert_pre = double2loc_format(val * 100 + 0.5); + } else { + rr->vert_pre = double2loc_format(10 * 100 + 0.5); + } + } else { + rr->horiz_pre = double2loc_format(10000 * 100 + 0.5); + } + } else { + rr->size = double2loc_format(1 * 100 + 0.5); + } + + if (*s) { + return bitch("garbage after valid LOC data"); + } + + return store_record(type, name, ttl, rr); } static char* loc_human(struct rr *rrv) @@ -185,17 +185,17 @@ static char* loc_human(struct rr *rrv) // snprintf(s, 1024, "\"%s\" \"%s\"", rr->cpu.data, rr->os.data); // return quickstrdup_temp(s); - return "meow"; + return "meow"; } static struct binary_data loc_wirerdata(struct rr *rrv) { - RRCAST(loc); + RRCAST(loc); return compose_binary_data("1111444", 1, - rr->version, rr->size, - rr->horiz_pre, rr->vert_pre, - rr->latitude, rr->longitude, rr->altitude); + rr->version, rr->size, + rr->horiz_pre, rr->vert_pre, + rr->latitude, rr->longitude, rr->altitude); } struct rr_methods loc_methods = { loc_parse, loc_human, loc_wirerdata, NULL, NULL }; diff --git a/lp.c b/lp.c index ddf5aa3..d93cabb 100644 --- a/lp.c +++ b/lp.c @@ -20,41 +20,41 @@ static struct rr *lp_parse(char *name, long ttl, int type, char *s) { - struct rr_lp *rr = getmem(sizeof(*rr)); - int preference; - - rr->preference = preference = extract_integer(&s, "LP preference", NULL); - if (preference < 0) - return NULL; - rr->fqdn = extract_name(&s, "LP fqdn", 0); - if (!rr->fqdn) - return NULL; - if (strcasecmp(name, rr->fqdn) == 0) { - return bitch("LP points to itself"); - } - - if (*s) { - return bitch("garbage after valid LP data"); - } - - return store_record(type, name, ttl, rr); + struct rr_lp *rr = getmem(sizeof(*rr)); + int preference; + + rr->preference = preference = extract_integer(&s, "LP preference", NULL); + if (preference < 0) + return NULL; + rr->fqdn = extract_name(&s, "LP fqdn", 0); + if (!rr->fqdn) + return NULL; + if (strcasecmp(name, rr->fqdn) == 0) { + return bitch("LP points to itself"); + } + + if (*s) { + return bitch("garbage after valid LP data"); + } + + return store_record(type, name, ttl, rr); } static char* lp_human(struct rr *rrv) { - RRCAST(lp); - char s[1024]; + RRCAST(lp); + char s[1024]; - snprintf(s, 1024, "%d %s", - rr->preference, rr->fqdn); - return quickstrdup_temp(s); + snprintf(s, 1024, "%d %s", + rr->preference, rr->fqdn); + return quickstrdup_temp(s); } static struct binary_data lp_wirerdata(struct rr *rrv) { - RRCAST(lp); + RRCAST(lp); return compose_binary_data("2d", 1, - rr->preference, name2wire_name(rr->fqdn)); + rr->preference, name2wire_name(rr->fqdn)); } struct rr_methods lp_methods = { lp_parse, lp_human, lp_wirerdata, NULL, NULL }; diff --git a/main.c b/main.c index 2b6a79f..c6e65d1 100644 --- a/main.c +++ b/main.c @@ -34,609 +34,609 @@ void open_zone_file(char *fname); static void concat_generate_template(char *buf, int bufsz, int val, struct generate_template_piece *t) { - char sval[40]; - - while (t) { - if (t->constant_string) { - mystrlcat(buf, t->constant_string, bufsz); - } else { - snprintf(sval, 40, "%d", val); - mystrlcat(buf, sval, bufsz); - } - t = t->next; - } + char sval[40]; + + while (t) { + if (t->constant_string) { + mystrlcat(buf, t->constant_string, bufsz); + } else { + snprintf(sval, 40, "%d", val); + mystrlcat(buf, sval, bufsz); + } + t = t->next; + } } static struct generate_template_piece * free_generate_template(struct generate_template_piece *t) { - struct generate_template_piece *n; - while (t) { - n = t->next; - free(t); - t = n; - } - return NULL; + struct generate_template_piece *n; + while (t) { + n = t->next; + free(t); + t = n; + } + return NULL; } static void create_generate_template_piece(struct generate_template_piece **generate_template, char *s) { - if (s && *s == 0) - return; - - struct generate_template_piece *p = malloc(sizeof(struct generate_template_piece)); - - p->constant_string = s; - p->next = NULL; - - if (*generate_template) { - struct generate_template_piece *t = *generate_template; - while (t->next) - t = t->next; - t->next = p; - } else { - *generate_template = p; - } + if (s && *s == 0) + return; + + struct generate_template_piece *p = malloc(sizeof(struct generate_template_piece)); + + p->constant_string = s; + p->next = NULL; + + if (*generate_template) { + struct generate_template_piece *t = *generate_template; + while (t->next) + t = t->next; + t->next = p; + } else { + *generate_template = p; + } } static struct generate_template_piece * prepare_generate_template(char *t) { - char *s = t; - struct generate_template_piece *r = NULL; - - while (1) { - while (*t && *t != '$') t++; - if (!*t) { - create_generate_template_piece(&r, s); - break; - } else { - *t = 0; - create_generate_template_piece(&r, s); - create_generate_template_piece(&r, NULL); - t++; - s = t; - } - } - - return r; + char *s = t; + struct generate_template_piece *r = NULL; + + while (1) { + while (*t && *t != '$') t++; + if (!*t) { + create_generate_template_piece(&r, s); + break; + } else { + *t = 0; + create_generate_template_piece(&r, s); + create_generate_template_piece(&r, NULL); + t++; + s = t; + } + } + + return r; } static char *process_directive(char *s) { - char *d = s+1; - if (*(s+1) == 'O' && strncmp(s, "$ORIGIN", 7) == 0) { - char *o; - s += 7; - if (!isspace(*s)) { - if (isalnum(*s)) goto unrecognized_directive; - return bitch("bad $ORIGIN format"); - } - s = skip_white_space(s); - o = extract_name(&s, "$ORIGIN value", 0); - if (!o) { - return NULL; - } - if (*s) { - return bitch("garbage after valid $ORIGIN directive"); - } - file_info->current_origin = o; - if (G.opt.verbose) { - fprintf(stderr, "-> %s:%d: ", file_info->name, file_info->line); - fprintf(stderr, "origin is now %s\n", o); - } - } else if (*(s+1) == 'T' && strncmp(s, "$TTL", 4) == 0) { - s += 4; - if (!isspace(*s)) { - if (isalnum(*s)) goto unrecognized_directive; - return bitch("bad $TTL format"); - } - s = skip_white_space(s); - G.default_ttl = extract_timevalue(&s, "$TTL value"); - if (G.default_ttl < 0) { - return NULL; - } - if (*s) { - return bitch("garbage after valid $TTL directive"); - } - if (G.opt.verbose) { - fprintf(stderr, "-> %s:%d: ", file_info->name, file_info->line); - fprintf(stderr, "default ttl is now %ld\n", G.default_ttl); - } - } else if (*(s+1) == 'G' && strncmp(s, "$GENERATE", 9) == 0) { - int from, to; - char *lhs, *rdtype; - - s += 9; - if (!isspace(*s)) { - if (isalnum(*s)) goto unrecognized_directive; - return bitch("bad $GENERATE format"); - } - s = skip_white_space(s); - - from = extract_integer(&s, "generate-from", "-"); - if (from < 0) - return NULL; - if (*s != '-') - return bitch("'-' between generate-from and generate-to is expected"); - s++; - to = extract_integer(&s, "generate-to", "-"); - if (to < 0) - return NULL; - - if (*s == '/') - return bitch("generate-step is unsupported for now"); - - lhs = extract_name(&s, "generate-lhs", KEEP_CAPITALIZATION | DOLLAR_OK_IN_NAMES); - if (!lhs) - return NULL; - - if (*s == '{') - return bitch("{offset,width,type} is unsupported for now"); - - rdtype = extract_label(&s, "type", NULL); - if (!rdtype) - return NULL; - - file_info->generate_cur = from; - file_info->generate_lim = to; - file_info->generate_type = rdtype; - file_info->generate_lhs = prepare_generate_template(lhs); - file_info->generate_rhs = prepare_generate_template(quickstrdup(s)); - - return s; - } else if (*(s+1) == 'I' && strncmp(s, "$INCLUDE", 8) == 0) { - char *p, *f; - char c; - s += 8; - if (!isspace(*s)) { - if (isalnum(*s)) goto unrecognized_directive; - return bitch("bad $INCLUDE format"); - } - s = skip_white_space(s); - p = s; - while (*s && !isspace(*s) && *s != ';') - s++; - c = *s; - *s = '\0'; - if (!*p) { - return bitch("$INCLUDE directive with empty file name"); - } - f = quickstrdup_temp(p); - *s = c; - s = skip_white_space(s); - - if (*s) { - return bitch("garbage after valid $INCLUDE directive"); - } - if (*f == '/') { - open_zone_file(f); - } else { - char buf[1024]; - - snprintf(buf, 1024, "%s/%s", G.opt.include_path, f); - open_zone_file(buf); - } - } else { + char *d = s+1; + if (*(s+1) == 'O' && strncmp(s, "$ORIGIN", 7) == 0) { + char *o; + s += 7; + if (!isspace(*s)) { + if (isalnum(*s)) goto unrecognized_directive; + return bitch("bad $ORIGIN format"); + } + s = skip_white_space(s); + o = extract_name(&s, "$ORIGIN value", 0); + if (!o) { + return NULL; + } + if (*s) { + return bitch("garbage after valid $ORIGIN directive"); + } + file_info->current_origin = o; + if (G.opt.verbose) { + fprintf(stderr, "-> %s:%d: ", file_info->name, file_info->line); + fprintf(stderr, "origin is now %s\n", o); + } + } else if (*(s+1) == 'T' && strncmp(s, "$TTL", 4) == 0) { + s += 4; + if (!isspace(*s)) { + if (isalnum(*s)) goto unrecognized_directive; + return bitch("bad $TTL format"); + } + s = skip_white_space(s); + G.default_ttl = extract_timevalue(&s, "$TTL value"); + if (G.default_ttl < 0) { + return NULL; + } + if (*s) { + return bitch("garbage after valid $TTL directive"); + } + if (G.opt.verbose) { + fprintf(stderr, "-> %s:%d: ", file_info->name, file_info->line); + fprintf(stderr, "default ttl is now %ld\n", G.default_ttl); + } + } else if (*(s+1) == 'G' && strncmp(s, "$GENERATE", 9) == 0) { + int from, to; + char *lhs, *rdtype; + + s += 9; + if (!isspace(*s)) { + if (isalnum(*s)) goto unrecognized_directive; + return bitch("bad $GENERATE format"); + } + s = skip_white_space(s); + + from = extract_integer(&s, "generate-from", "-"); + if (from < 0) + return NULL; + if (*s != '-') + return bitch("'-' between generate-from and generate-to is expected"); + s++; + to = extract_integer(&s, "generate-to", "-"); + if (to < 0) + return NULL; + + if (*s == '/') + return bitch("generate-step is unsupported for now"); + + lhs = extract_name(&s, "generate-lhs", KEEP_CAPITALIZATION | DOLLAR_OK_IN_NAMES); + if (!lhs) + return NULL; + + if (*s == '{') + return bitch("{offset,width,type} is unsupported for now"); + + rdtype = extract_label(&s, "type", NULL); + if (!rdtype) + return NULL; + + file_info->generate_cur = from; + file_info->generate_lim = to; + file_info->generate_type = rdtype; + file_info->generate_lhs = prepare_generate_template(lhs); + file_info->generate_rhs = prepare_generate_template(quickstrdup(s)); + + return s; + } else if (*(s+1) == 'I' && strncmp(s, "$INCLUDE", 8) == 0) { + char *p, *f; + char c; + s += 8; + if (!isspace(*s)) { + if (isalnum(*s)) goto unrecognized_directive; + return bitch("bad $INCLUDE format"); + } + s = skip_white_space(s); + p = s; + while (*s && !isspace(*s) && *s != ';') + s++; + c = *s; + *s = '\0'; + if (!*p) { + return bitch("$INCLUDE directive with empty file name"); + } + f = quickstrdup_temp(p); + *s = c; + s = skip_white_space(s); + + if (*s) { + return bitch("garbage after valid $INCLUDE directive"); + } + if (*f == '/') { + open_zone_file(f); + } else { + char buf[1024]; + + snprintf(buf, 1024, "%s/%s", G.opt.include_path, f); + open_zone_file(buf); + } + } else { unrecognized_directive: - s = d-1; - while (isalnum(*d)) d++; - *d = '\0'; - return bitch("unrecognized directive: %s", s); - } - return s; + s = d-1; + while (isalnum(*d)) d++; + *d = '\0'; + return bitch("unrecognized directive: %s", s); + } + return s; } char * read_zone_line(void) { - char *r; - - if (file_info->generate_lhs) { - if (file_info->generate_cur <= file_info->generate_lim) { - file_info->buf[0] = 0; - concat_generate_template(file_info->buf, LINEBUFSZ, file_info->generate_cur, file_info->generate_lhs); - mystrlcat(file_info->buf, " ", LINEBUFSZ); - mystrlcat(file_info->buf, file_info->generate_type, LINEBUFSZ); - mystrlcat(file_info->buf, " ", LINEBUFSZ); - concat_generate_template(file_info->buf, LINEBUFSZ, file_info->generate_cur, file_info->generate_rhs); - file_info->generate_cur++; - return file_info->buf; - } else { - /* Done with this $GENERATE */ - file_info->generate_cur = 0; - file_info->generate_lim = 0; - file_info->generate_type = NULL; - file_info->generate_lhs = NULL; - free_generate_template(file_info->generate_lhs); - free_generate_template(file_info->generate_rhs); - file_info->generate_rhs = NULL; - } - } - - r = fgets(file_info->buf, LINEBUFSZ, file_info->file); - if (r) - file_info->line++; - return r; + char *r; + + if (file_info->generate_lhs) { + if (file_info->generate_cur <= file_info->generate_lim) { + file_info->buf[0] = 0; + concat_generate_template(file_info->buf, LINEBUFSZ, file_info->generate_cur, file_info->generate_lhs); + mystrlcat(file_info->buf, " ", LINEBUFSZ); + mystrlcat(file_info->buf, file_info->generate_type, LINEBUFSZ); + mystrlcat(file_info->buf, " ", LINEBUFSZ); + concat_generate_template(file_info->buf, LINEBUFSZ, file_info->generate_cur, file_info->generate_rhs); + file_info->generate_cur++; + return file_info->buf; + } else { + /* Done with this $GENERATE */ + file_info->generate_cur = 0; + file_info->generate_lim = 0; + file_info->generate_type = NULL; + file_info->generate_lhs = NULL; + free_generate_template(file_info->generate_lhs); + free_generate_template(file_info->generate_rhs); + file_info->generate_rhs = NULL; + } + } + + r = fgets(file_info->buf, LINEBUFSZ, file_info->file); + if (r) + file_info->line++; + return r; } int read_zone_file(void) { - char *s; - char *name = NULL, *class, *rdtype; - long ttl = -1; - while (file_info) { - while (read_zone_line()) { - freeall_temp(); - file_info->paren_mode = 0; - rdtype = NULL; - if (empty_line_or_comment(file_info->buf)) - continue; - - s = file_info->buf; - if (!isspace(*s)) { - /* , $INCLUDE, $ORIGIN */ - if (*s == '$') { - process_directive(s); - continue; - } else { - /* */ - name = extract_name(&s, "record name", 0); - if (!name) - continue; - } - } else { - s = skip_white_space(s); - } - if (!s) - continue; - if (!name) { - bitch("cannot assume previous name for it is not known"); - continue; - } - if (G.default_ttl >= 0) - ttl = G.default_ttl; - if (isdigit(*s)) { - ttl = extract_timevalue(&s, "TTL"); - if (ttl < 0) - continue; - class = extract_label(&s, "class or type", "temporary"); - if (!class) - continue; - if (*class == 'i' && *(class+1) == 'n' && *(class+2) == 0) { - } else if (*class == 'c' && *(class+1) == 's' && *(class+2) == 0) { - bitch("CSNET class is not supported"); - continue; - } else if (*class == 'c' && *(class+1) == 'h' && *(class+2) == 0) { - bitch("CHAOS class is not supported"); - continue; - } else if (*class == 'h' && *(class+1) == 's' && *(class+2) == 0) { - bitch("HESIOD class is not supported"); - continue; - } else { - rdtype = class; - } - } else { - class = extract_label(&s, "class or type", "temporary"); - if (!class) - continue; - if (*class == 'i' && *(class+1) == 'n' && *(class+2) == 0) { - if (isdigit(*s)) { - ttl = extract_timevalue(&s, "TTL"); - if (ttl < 0) - continue; - } - } else if (*class == 'c' && *(class+1) == 's' && *(class+2) == 0) { - bitch("CSNET class is not supported"); - continue; - } else if (*class == 'c' && *(class+1) == 'h' && *(class+2) == 0) { - bitch("CHAOS class is not supported"); - continue; - } else if (*class == 'h' && *(class+1) == 's' && *(class+2) == 0) { - bitch("HESIOD class is not supported"); - continue; - } else { - rdtype = class; - } - } - if (!rdtype) { - rdtype = extract_label(&s, "type", "temporary"); - } - if (!rdtype) { - continue; - } - if (ttl < 0) { - ttl = G.default_ttl; - } - - { - int is_generic; - int type = str2rdtype(rdtype, &is_generic); - struct rr *rr; - - if (type <= 0) continue; - - if (ttl < 0 && !(G.opt.soa_minttl_as_default_ttl && type == T_SOA)) { - bitch("ttl not specified and default is not known"); - continue; - } - - if (is_generic) - rr = rr_parse_any(name, ttl, type, s); - else if (type > T_MAX) - rr = rr_parse_any(name, ttl, type, s); - else if (rr_methods[type].rr_parse) - rr = rr_methods[type].rr_parse(name, ttl, type, s); - else - rr = rr_parse_any(name, ttl, type, s); - - if (type == T_SOA && ttl < 0 && rr) { - struct rr_soa *soa = (struct rr_soa *) rr; - soa->rr.ttl = G.default_ttl = soa->minimum; - if (G.opt.verbose) { - fprintf(stderr, "-> %s:%d: ", file_info->name, file_info->line); - fprintf(stderr, "no ttl specified; using SOA MINTTL (%ld) instead\n", G.default_ttl); - } - } - } - } - if (ferror(file_info->file)) - croak(1, "read error for %s", file_info->name); - file_info = file_info->next; - } - return 0; + char *s; + char *name = NULL, *class, *rdtype; + long ttl = -1; + while (file_info) { + while (read_zone_line()) { + freeall_temp(); + file_info->paren_mode = 0; + rdtype = NULL; + if (empty_line_or_comment(file_info->buf)) + continue; + + s = file_info->buf; + if (!isspace(*s)) { + /* , $INCLUDE, $ORIGIN */ + if (*s == '$') { + process_directive(s); + continue; + } else { + /* */ + name = extract_name(&s, "record name", 0); + if (!name) + continue; + } + } else { + s = skip_white_space(s); + } + if (!s) + continue; + if (!name) { + bitch("cannot assume previous name for it is not known"); + continue; + } + if (G.default_ttl >= 0) + ttl = G.default_ttl; + if (isdigit(*s)) { + ttl = extract_timevalue(&s, "TTL"); + if (ttl < 0) + continue; + class = extract_label(&s, "class or type", "temporary"); + if (!class) + continue; + if (*class == 'i' && *(class+1) == 'n' && *(class+2) == 0) { + } else if (*class == 'c' && *(class+1) == 's' && *(class+2) == 0) { + bitch("CSNET class is not supported"); + continue; + } else if (*class == 'c' && *(class+1) == 'h' && *(class+2) == 0) { + bitch("CHAOS class is not supported"); + continue; + } else if (*class == 'h' && *(class+1) == 's' && *(class+2) == 0) { + bitch("HESIOD class is not supported"); + continue; + } else { + rdtype = class; + } + } else { + class = extract_label(&s, "class or type", "temporary"); + if (!class) + continue; + if (*class == 'i' && *(class+1) == 'n' && *(class+2) == 0) { + if (isdigit(*s)) { + ttl = extract_timevalue(&s, "TTL"); + if (ttl < 0) + continue; + } + } else if (*class == 'c' && *(class+1) == 's' && *(class+2) == 0) { + bitch("CSNET class is not supported"); + continue; + } else if (*class == 'c' && *(class+1) == 'h' && *(class+2) == 0) { + bitch("CHAOS class is not supported"); + continue; + } else if (*class == 'h' && *(class+1) == 's' && *(class+2) == 0) { + bitch("HESIOD class is not supported"); + continue; + } else { + rdtype = class; + } + } + if (!rdtype) { + rdtype = extract_label(&s, "type", "temporary"); + } + if (!rdtype) { + continue; + } + if (ttl < 0) { + ttl = G.default_ttl; + } + + { + int is_generic; + int type = str2rdtype(rdtype, &is_generic); + struct rr *rr; + + if (type <= 0) continue; + + if (ttl < 0 && !(G.opt.soa_minttl_as_default_ttl && type == T_SOA)) { + bitch("ttl not specified and default is not known"); + continue; + } + + if (is_generic) + rr = rr_parse_any(name, ttl, type, s); + else if (type > T_MAX) + rr = rr_parse_any(name, ttl, type, s); + else if (rr_methods[type].rr_parse) + rr = rr_methods[type].rr_parse(name, ttl, type, s); + else + rr = rr_parse_any(name, ttl, type, s); + + if (type == T_SOA && ttl < 0 && rr) { + struct rr_soa *soa = (struct rr_soa *) rr; + soa->rr.ttl = G.default_ttl = soa->minimum; + if (G.opt.verbose) { + fprintf(stderr, "-> %s:%d: ", file_info->name, file_info->line); + fprintf(stderr, "no ttl specified; using SOA MINTTL (%ld) instead\n", G.default_ttl); + } + } + } + } + if (ferror(file_info->file)) + croak(1, "read error for %s", file_info->name); + file_info = file_info->next; + } + return 0; } void open_zone_file(char *fname) { - FILE *f; - struct file_info *new_file_info; - - if (strcmp(fname, "-") == 0) { - f = stdin; - fname = "stdin"; - } else { - f = fopen(fname, "r"); - if (!file_info && !G.opt.include_path_specified) { - G.opt.include_path = quickstrdup(dirname(quickstrdup_temp(fname))); - } - } - if (!f) - croak(1, "open %s", fname); - new_file_info = malloc(sizeof(*new_file_info) + strlen(fname) + 1); - if (!new_file_info) - croak(1, "malloc(file_info), %s", fname); - new_file_info->next = file_info; - new_file_info->file = f; - new_file_info->line = 0; - strcpy(new_file_info->name, fname); - if (file_info) { - new_file_info->current_origin = file_info->current_origin; - } else { - new_file_info->current_origin = G.opt.first_origin; - } - file_info = new_file_info; + FILE *f; + struct file_info *new_file_info; + + if (strcmp(fname, "-") == 0) { + f = stdin; + fname = "stdin"; + } else { + f = fopen(fname, "r"); + if (!file_info && !G.opt.include_path_specified) { + G.opt.include_path = quickstrdup(dirname(quickstrdup_temp(fname))); + } + } + if (!f) + croak(1, "open %s", fname); + new_file_info = malloc(sizeof(*new_file_info) + strlen(fname) + 1); + if (!new_file_info) + croak(1, "malloc(file_info), %s", fname); + new_file_info->next = file_info; + new_file_info->file = f; + new_file_info->line = 0; + strcpy(new_file_info->name, fname); + if (file_info) { + new_file_info->current_origin = file_info->current_origin; + } else { + new_file_info->current_origin = G.opt.first_origin; + } + file_info = new_file_info; } void usage(char *err) { - if (err) - fprintf(stderr, "%s\n", err); - fprintf(stderr, "Usage:\n"); - fprintf(stderr, " %s -h\n", thisprogname()); - fprintf(stderr, " %s [options] zone-file\n", thisprogname()); - fprintf(stderr, "Usage parameters:\n"); - fprintf(stderr, "\t-h\t\tproduce usage text and quit\n"); - fprintf(stderr, "\t-f\t\tquit on first validation error\n"); - - fprintf(stderr, "\t-p name\tperform policy check \n"); - fprintf(stderr, "\t\t\tsingle-ns\n"); - fprintf(stderr, "\t\t\tcname-other-data\n"); - fprintf(stderr, "\t\t\tdname\n"); - fprintf(stderr, "\t\t\tnsec3param-not-apex\n"); - fprintf(stderr, "\t\t\tmx-alias\n"); - fprintf(stderr, "\t\t\tns-alias\n"); - fprintf(stderr, "\t\t\trp-txt-exists\n"); - fprintf(stderr, "\t\t\ttlsa-host\n"); - fprintf(stderr, "\t\t\tksk-exists\n"); - fprintf(stderr, "\t\t\tall\n"); - - fprintf(stderr, "\t-n N\t\tuse N worker threads\n"); - fprintf(stderr, "\t-q\t\tquiet - do not produce any output\n"); - fprintf(stderr, "\t-s\t\tprint validation summary/stats\n"); - fprintf(stderr, "\t-v\t\tbe extra verbose\n"); - fprintf(stderr, "\t-I path\tuse this path for $INCLUDE files\n"); - fprintf(stderr, "\t-z origin\tuse this origin as initial $ORIGIN\n"); - fprintf(stderr, "\t-t epoch-time\tuse this time instead of \"now\"\n"); - exit(1); + if (err) + fprintf(stderr, "%s\n", err); + fprintf(stderr, "Usage:\n"); + fprintf(stderr, " %s -h\n", thisprogname()); + fprintf(stderr, " %s [options] zone-file\n", thisprogname()); + fprintf(stderr, "Usage parameters:\n"); + fprintf(stderr, "\t-h\t\tproduce usage text and quit\n"); + fprintf(stderr, "\t-f\t\tquit on first validation error\n"); + + fprintf(stderr, "\t-p name\tperform policy check \n"); + fprintf(stderr, "\t\t\tsingle-ns\n"); + fprintf(stderr, "\t\t\tcname-other-data\n"); + fprintf(stderr, "\t\t\tdname\n"); + fprintf(stderr, "\t\t\tnsec3param-not-apex\n"); + fprintf(stderr, "\t\t\tmx-alias\n"); + fprintf(stderr, "\t\t\tns-alias\n"); + fprintf(stderr, "\t\t\trp-txt-exists\n"); + fprintf(stderr, "\t\t\ttlsa-host\n"); + fprintf(stderr, "\t\t\tksk-exists\n"); + fprintf(stderr, "\t\t\tall\n"); + + fprintf(stderr, "\t-n N\t\tuse N worker threads\n"); + fprintf(stderr, "\t-q\t\tquiet - do not produce any output\n"); + fprintf(stderr, "\t-s\t\tprint validation summary/stats\n"); + fprintf(stderr, "\t-v\t\tbe extra verbose\n"); + fprintf(stderr, "\t-I path\tuse this path for $INCLUDE files\n"); + fprintf(stderr, "\t-z origin\tuse this origin as initial $ORIGIN\n"); + fprintf(stderr, "\t-t epoch-time\tuse this time instead of \"now\"\n"); + exit(1); } struct rr_methods rr_methods[T_MAX+1]; static void initialize_globals(void) { - int i; - - setenv("TZ", "GMT0", 1); tzset(); - memset(&G, 0, sizeof(G)); - memset(&G.opt, 0, sizeof(G.opt)); - memset(&G.stats, 0, sizeof(G.stats)); - G.default_ttl = -1; /* XXX orly? */ - G.opt.times_to_check[0] = time(NULL); - G.opt.n_times_to_check = 0; - G.opt.include_path = "."; - - for (i = 0; i <= T_MAX; i++) { - rr_methods[i] = unknown_methods; - } - rr_methods[T_AAAA] = aaaa_methods; - rr_methods[T_A] = a_methods; - rr_methods[T_AFSDB] = afsdb_methods; - rr_methods[T_CERT] = cert_methods; - rr_methods[T_CNAME] = cname_methods; - rr_methods[T_DHCID] = dhcid_methods; - rr_methods[T_DLV] = dlv_methods; - rr_methods[T_DNAME] = dname_methods; - rr_methods[T_DNSKEY] = dnskey_methods; - rr_methods[T_DS] = ds_methods; - rr_methods[T_HINFO] = hinfo_methods; - rr_methods[T_IPSECKEY] = ipseckey_methods; - rr_methods[T_ISDN] = isdn_methods; - rr_methods[T_KX] = kx_methods; - rr_methods[T_L32] = l32_methods; - rr_methods[T_L64] = l64_methods; - rr_methods[T_LOC] = loc_methods; - rr_methods[T_LP] = lp_methods; - rr_methods[T_MB] = mb_methods; - rr_methods[T_MG] = mg_methods; - rr_methods[T_MINFO] = minfo_methods; - rr_methods[T_MR] = mr_methods; - rr_methods[T_MX] = mx_methods; - rr_methods[T_NAPTR] = naptr_methods; - rr_methods[T_NID] = nid_methods; - rr_methods[T_NSAP] = nsap_methods; - rr_methods[T_NSEC3PARAM] = nsec3param_methods; - rr_methods[T_NSEC3] = nsec3_methods; - rr_methods[T_NSEC] = nsec_methods; - rr_methods[T_NS] = ns_methods; - rr_methods[T_PTR] = ptr_methods; - rr_methods[T_PX] = px_methods; - rr_methods[T_RP] = rp_methods; - rr_methods[T_RT] = rt_methods; - rr_methods[T_RRSIG] = rrsig_methods; - rr_methods[T_SOA] = soa_methods; - rr_methods[T_SPF] = spf_methods; - rr_methods[T_SRV] = srv_methods; - rr_methods[T_SSHFP] = sshfp_methods; - rr_methods[T_TLSA] = tlsa_methods; - rr_methods[T_TXT] = txt_methods; - rr_methods[T_X25] = x25_methods; + int i; + + setenv("TZ", "GMT0", 1); tzset(); + memset(&G, 0, sizeof(G)); + memset(&G.opt, 0, sizeof(G.opt)); + memset(&G.stats, 0, sizeof(G.stats)); + G.default_ttl = -1; /* XXX orly? */ + G.opt.times_to_check[0] = time(NULL); + G.opt.n_times_to_check = 0; + G.opt.include_path = "."; + + for (i = 0; i <= T_MAX; i++) { + rr_methods[i] = unknown_methods; + } + rr_methods[T_AAAA] = aaaa_methods; + rr_methods[T_A] = a_methods; + rr_methods[T_AFSDB] = afsdb_methods; + rr_methods[T_CERT] = cert_methods; + rr_methods[T_CNAME] = cname_methods; + rr_methods[T_DHCID] = dhcid_methods; + rr_methods[T_DLV] = dlv_methods; + rr_methods[T_DNAME] = dname_methods; + rr_methods[T_DNSKEY] = dnskey_methods; + rr_methods[T_DS] = ds_methods; + rr_methods[T_HINFO] = hinfo_methods; + rr_methods[T_IPSECKEY] = ipseckey_methods; + rr_methods[T_ISDN] = isdn_methods; + rr_methods[T_KX] = kx_methods; + rr_methods[T_L32] = l32_methods; + rr_methods[T_L64] = l64_methods; + rr_methods[T_LOC] = loc_methods; + rr_methods[T_LP] = lp_methods; + rr_methods[T_MB] = mb_methods; + rr_methods[T_MG] = mg_methods; + rr_methods[T_MINFO] = minfo_methods; + rr_methods[T_MR] = mr_methods; + rr_methods[T_MX] = mx_methods; + rr_methods[T_NAPTR] = naptr_methods; + rr_methods[T_NID] = nid_methods; + rr_methods[T_NSAP] = nsap_methods; + rr_methods[T_NSEC3PARAM] = nsec3param_methods; + rr_methods[T_NSEC3] = nsec3_methods; + rr_methods[T_NSEC] = nsec_methods; + rr_methods[T_NS] = ns_methods; + rr_methods[T_PTR] = ptr_methods; + rr_methods[T_PX] = px_methods; + rr_methods[T_RP] = rp_methods; + rr_methods[T_RT] = rt_methods; + rr_methods[T_RRSIG] = rrsig_methods; + rr_methods[T_SOA] = soa_methods; + rr_methods[T_SPF] = spf_methods; + rr_methods[T_SRV] = srv_methods; + rr_methods[T_SSHFP] = sshfp_methods; + rr_methods[T_TLSA] = tlsa_methods; + rr_methods[T_TXT] = txt_methods; + rr_methods[T_X25] = x25_methods; } int main(int argc, char **argv) { - int o; - struct timeval start, stop; - - initialize_globals(); - while ((o = getopt(argc, argv, "fhMqsvI:z:t:p:n:")) != -1) { - switch(o) { - case 'h': - usage(NULL); - break; - case 'f': - G.opt.die_on_first_error = 1; - break; - case 'M': - G.opt.soa_minttl_as_default_ttl = 1; - break; - case 'q': - G.opt.no_output = 1; - break; - case 's': - G.opt.summary = 1; - break; - case 'v': - G.opt.verbose = 1; - break; - case 'p': - if (strcmp(optarg, "all") == 0) { - int i; - for (i = 0; i < N_POLICY_CHECKS; i++) { - G.opt.policy_checks[i] = 1; - } - } else if (strcmp(optarg, "single-ns") == 0) { - G.opt.policy_checks[POLICY_SINGLE_NS] = 1; - } else if (strcmp(optarg, "cname-other-data") == 0) { - G.opt.policy_checks[POLICY_CNAME_OTHER_DATA] = 1; - } else if (strcmp(optarg, "dname") == 0) { - G.opt.policy_checks[POLICY_DNAME] = 1; - } else if (strcmp(optarg, "dnskey") == 0) { - G.opt.policy_checks[POLICY_DNSKEY] = 1; - } else if (strcmp(optarg, "nsec3param-not-apex") == 0) { - G.opt.policy_checks[POLICY_NSEC3PARAM_NOT_APEX] = 1; - } else if (strcmp(optarg, "mx-alias") == 0) { - G.opt.policy_checks[POLICY_MX_ALIAS] = 1; - } else if (strcmp(optarg, "ns-alias") == 0) { - G.opt.policy_checks[POLICY_NS_ALIAS] = 1; - } else if (strcmp(optarg, "rp-txt-exists") == 0) { - G.opt.policy_checks[POLICY_RP_TXT_EXISTS] = 1; - } else if (strcmp(optarg, "tlsa-host") == 0) { - G.opt.policy_checks[POLICY_TLSA_HOST] = 1; - } else if (strcmp(optarg, "ksk-exists") == 0) { - G.opt.policy_checks[POLICY_KSK_EXISTS] = 1; - } else { - usage("unknown policy name"); - } - break; - case 'I': - G.opt.include_path = optarg; - G.opt.include_path_specified = 1; - break; - case 'z': - if (strlen(optarg) && *(optarg+strlen(optarg)-1) == '.') { - G.opt.first_origin = optarg; - } else if (strlen(optarg)) { - G.opt.first_origin = getmem(strlen(optarg)+2); - strcpy(mystpcpy(G.opt.first_origin, optarg), "."); - } else { - usage("origin must not be empty"); - } - break; - case 'n': - G.opt.n_threads = strtol(optarg, NULL, 10); - if (G.opt.n_threads > 256) - usage("non-sensical number of threads requested"); - if (G.opt.verbose) - fprintf(stderr, "using %d worker threads\n", G.opt.n_threads); - break; - case 't': - if (G.opt.n_times_to_check >= MAX_TIMES_TO_CHECK) - usage("too many -t specified"); - G.opt.times_to_check[G.opt.n_times_to_check++] = strtol(optarg, NULL, 10); - break; - default: - usage(NULL); - } - } - if (G.opt.n_times_to_check <= 0) - G.opt.n_times_to_check = 1; - argc -= optind; - argv += optind; - if (argc != 1) - usage(NULL); - gettimeofday(&start, NULL); - open_zone_file(argv[0]); - read_zone_file(); - validate_zone(); - verify_all_keys(); - if (G.nsec3_present) { - if (first_nsec3) nsec3_validate(&first_nsec3->rr); - perform_remaining_nsec3checks(); - } - if (G.dnssec_active && G.opt.policy_checks[POLICY_KSK_EXISTS]) { - dnskey_ksk_policy_check(); - } - gettimeofday(&stop, NULL); - if (G.opt.summary) { - printf("records found: %d\n", G.stats.rr_count); - printf("skipped dups: %d\n", G.stats.skipped_dup_rr_count); - printf("record sets found: %d\n", G.stats.rrset_count); - printf("unique names found: %d\n", G.stats.names_count); - printf("delegations found: %d\n", G.stats.delegations); - printf(" nsec3 records: %d\n", G.stats.nsec3_count); - /* "not authoritative names" - non-empty terminals without any authoritative records */ - /* delegation points count as authoritative, which might or might not be correct */ - printf("not authoritative names, not counting delegation points:\n" - " %d\n", G.stats.not_authoritative); - printf("validation errors: %d\n", G.stats.error_count); - printf("signatures verified: %d\n", G.stats.signatures_verified); - printf("time taken: %.3fs\n", - stop.tv_sec - start.tv_sec + (stop.tv_usec - start.tv_usec)/1000000.); - } - return G.exit_code; + int o; + struct timeval start, stop; + + initialize_globals(); + while ((o = getopt(argc, argv, "fhMqsvI:z:t:p:n:")) != -1) { + switch(o) { + case 'h': + usage(NULL); + break; + case 'f': + G.opt.die_on_first_error = 1; + break; + case 'M': + G.opt.soa_minttl_as_default_ttl = 1; + break; + case 'q': + G.opt.no_output = 1; + break; + case 's': + G.opt.summary = 1; + break; + case 'v': + G.opt.verbose = 1; + break; + case 'p': + if (strcmp(optarg, "all") == 0) { + int i; + for (i = 0; i < N_POLICY_CHECKS; i++) { + G.opt.policy_checks[i] = 1; + } + } else if (strcmp(optarg, "single-ns") == 0) { + G.opt.policy_checks[POLICY_SINGLE_NS] = 1; + } else if (strcmp(optarg, "cname-other-data") == 0) { + G.opt.policy_checks[POLICY_CNAME_OTHER_DATA] = 1; + } else if (strcmp(optarg, "dname") == 0) { + G.opt.policy_checks[POLICY_DNAME] = 1; + } else if (strcmp(optarg, "dnskey") == 0) { + G.opt.policy_checks[POLICY_DNSKEY] = 1; + } else if (strcmp(optarg, "nsec3param-not-apex") == 0) { + G.opt.policy_checks[POLICY_NSEC3PARAM_NOT_APEX] = 1; + } else if (strcmp(optarg, "mx-alias") == 0) { + G.opt.policy_checks[POLICY_MX_ALIAS] = 1; + } else if (strcmp(optarg, "ns-alias") == 0) { + G.opt.policy_checks[POLICY_NS_ALIAS] = 1; + } else if (strcmp(optarg, "rp-txt-exists") == 0) { + G.opt.policy_checks[POLICY_RP_TXT_EXISTS] = 1; + } else if (strcmp(optarg, "tlsa-host") == 0) { + G.opt.policy_checks[POLICY_TLSA_HOST] = 1; + } else if (strcmp(optarg, "ksk-exists") == 0) { + G.opt.policy_checks[POLICY_KSK_EXISTS] = 1; + } else { + usage("unknown policy name"); + } + break; + case 'I': + G.opt.include_path = optarg; + G.opt.include_path_specified = 1; + break; + case 'z': + if (strlen(optarg) && *(optarg+strlen(optarg)-1) == '.') { + G.opt.first_origin = optarg; + } else if (strlen(optarg)) { + G.opt.first_origin = getmem(strlen(optarg)+2); + strcpy(mystpcpy(G.opt.first_origin, optarg), "."); + } else { + usage("origin must not be empty"); + } + break; + case 'n': + G.opt.n_threads = strtol(optarg, NULL, 10); + if (G.opt.n_threads > 256) + usage("non-sensical number of threads requested"); + if (G.opt.verbose) + fprintf(stderr, "using %d worker threads\n", G.opt.n_threads); + break; + case 't': + if (G.opt.n_times_to_check >= MAX_TIMES_TO_CHECK) + usage("too many -t specified"); + G.opt.times_to_check[G.opt.n_times_to_check++] = strtol(optarg, NULL, 10); + break; + default: + usage(NULL); + } + } + if (G.opt.n_times_to_check <= 0) + G.opt.n_times_to_check = 1; + argc -= optind; + argv += optind; + if (argc != 1) + usage(NULL); + gettimeofday(&start, NULL); + open_zone_file(argv[0]); + read_zone_file(); + validate_zone(); + verify_all_keys(); + if (G.nsec3_present) { + if (first_nsec3) nsec3_validate(&first_nsec3->rr); + perform_remaining_nsec3checks(); + } + if (G.dnssec_active && G.opt.policy_checks[POLICY_KSK_EXISTS]) { + dnskey_ksk_policy_check(); + } + gettimeofday(&stop, NULL); + if (G.opt.summary) { + printf("records found: %d\n", G.stats.rr_count); + printf("skipped dups: %d\n", G.stats.skipped_dup_rr_count); + printf("record sets found: %d\n", G.stats.rrset_count); + printf("unique names found: %d\n", G.stats.names_count); + printf("delegations found: %d\n", G.stats.delegations); + printf(" nsec3 records: %d\n", G.stats.nsec3_count); + /* "not authoritative names" - non-empty terminals without any authoritative records */ + /* delegation points count as authoritative, which might or might not be correct */ + printf("not authoritative names, not counting delegation points:\n" + " %d\n", G.stats.not_authoritative); + printf("validation errors: %d\n", G.stats.error_count); + printf("signatures verified: %d\n", G.stats.signatures_verified); + printf("time taken: %.3fs\n", + stop.tv_sec - start.tv_sec + (stop.tv_usec - start.tv_usec)/1000000.); + } + return G.exit_code; } diff --git a/mb.c b/mb.c index 7739f7a..66fa659 100644 --- a/mb.c +++ b/mb.c @@ -19,28 +19,28 @@ static struct rr *mb_parse(char *name, long ttl, int type, char *s) { - struct rr_mb *rr = getmem(sizeof(*rr)); + struct rr_mb *rr = getmem(sizeof(*rr)); - rr->madname = extract_name(&s, "madname", 0); - if (!rr->madname) - return NULL; - if (*s) { - return bitch("garbage after valid MB data"); - } + rr->madname = extract_name(&s, "madname", 0); + if (!rr->madname) + return NULL; + if (*s) { + return bitch("garbage after valid MB data"); + } - return store_record(type, name, ttl, rr); + return store_record(type, name, ttl, rr); } static char* mb_human(struct rr *rrv) { - RRCAST(mb); + RRCAST(mb); return rr->madname; } static struct binary_data mb_wirerdata(struct rr *rrv) { - RRCAST(mb); - return name2wire_name(rr->madname); + RRCAST(mb); + return name2wire_name(rr->madname); } struct rr_methods mb_methods = { mb_parse, mb_human, mb_wirerdata, NULL, NULL }; diff --git a/mempool.c b/mempool.c index 64f19a3..1e941ec 100644 --- a/mempool.c +++ b/mempool.c @@ -14,10 +14,10 @@ struct pool { - struct pool *next; - size_t pool_size; - size_t free_index; - char mem[0]; + struct pool *next; + size_t pool_size; + size_t free_index; + char mem[0]; }; static struct pool *freespace = NULL; @@ -25,78 +25,78 @@ static struct pool *temp_freespace = NULL; static void new_pool(size_t size) { - struct pool *pool; + struct pool *pool; - size = (size + sizeof(void *) - 1) / sizeof(void *); - size *= sizeof(void *); - pool = malloc(size + sizeof(struct pool)); - if (!pool) - croak(1, "new_pool malloc"); - pool->next = freespace; - pool->free_index = 0; - pool->pool_size = size; - freespace = pool; + size = (size + sizeof(void *) - 1) / sizeof(void *); + size *= sizeof(void *); + pool = malloc(size + sizeof(struct pool)); + if (!pool) + croak(1, "new_pool malloc"); + pool->next = freespace; + pool->free_index = 0; + pool->pool_size = size; + freespace = pool; } void mem_requirements_hint(size_t size) { - if (freespace) return; - new_pool(size); + if (freespace) return; + new_pool(size); } void *getmem(size_t size) { - void *ret; - size = (size + sizeof(void *) - 1) / sizeof(void *); - size *= sizeof(void *); - if (!freespace) new_pool(size > 256000 ? size : 256000); - if (freespace->pool_size - freespace->free_index < size) - new_pool(size > 256000 ? size : 256000); - ret = freespace->mem + freespace->free_index; - freespace->free_index += size; - return ret; + void *ret; + size = (size + sizeof(void *) - 1) / sizeof(void *); + size *= sizeof(void *); + if (!freespace) new_pool(size > 256000 ? size : 256000); + if (freespace->pool_size - freespace->free_index < size) + new_pool(size > 256000 ? size : 256000); + ret = freespace->mem + freespace->free_index; + freespace->free_index += size; + return ret; } void *getmem_temp(size_t size) { - void *ret; - size = (size + sizeof(void *) - 1) / sizeof(void *); - size *= sizeof(void *); - if (!temp_freespace) { - size_t pool_size = size > 1024*1024 ? size : 1024*1024; - pool_size = (pool_size + sizeof(void *) - 1) / sizeof(void *); - pool_size *= sizeof(void *); - temp_freespace = malloc(pool_size + sizeof(struct pool)); - if (!temp_freespace) - croak(1, "getmem_temp malloc"); - temp_freespace->next = NULL; - temp_freespace->free_index = 0; - temp_freespace->pool_size = pool_size; - } - if (temp_freespace->pool_size - temp_freespace->free_index < size) - croak(1, "getmem_temp request too large"); - ret = temp_freespace->mem + temp_freespace->free_index; - temp_freespace->free_index += size; - return ret; + void *ret; + size = (size + sizeof(void *) - 1) / sizeof(void *); + size *= sizeof(void *); + if (!temp_freespace) { + size_t pool_size = size > 1024*1024 ? size : 1024*1024; + pool_size = (pool_size + sizeof(void *) - 1) / sizeof(void *); + pool_size *= sizeof(void *); + temp_freespace = malloc(pool_size + sizeof(struct pool)); + if (!temp_freespace) + croak(1, "getmem_temp malloc"); + temp_freespace->next = NULL; + temp_freespace->free_index = 0; + temp_freespace->pool_size = pool_size; + } + if (temp_freespace->pool_size - temp_freespace->free_index < size) + croak(1, "getmem_temp request too large"); + ret = temp_freespace->mem + temp_freespace->free_index; + temp_freespace->free_index += size; + return ret; } int freeall_temp(void) { - if (temp_freespace) { - temp_freespace->free_index = 0; - } - return 1; + if (temp_freespace) { + temp_freespace->free_index = 0; + } + return 1; } char *quickstrdup(char *s) { - char *r = getmem(strlen(s)+1); - return strcpy(r, s); + char *r = getmem(strlen(s)+1); + return strcpy(r, s); } char *quickstrdup_temp(char *s) { - char *r = getmem_temp(strlen(s)+1); - return strcpy(r, s); + char *r = getmem_temp(strlen(s)+1); + return strcpy(r, s); } diff --git a/mg.c b/mg.c index 86166c0..1421de8 100644 --- a/mg.c +++ b/mg.c @@ -19,28 +19,28 @@ static struct rr *mg_parse(char *name, long ttl, int type, char *s) { - struct rr_mg *rr = getmem(sizeof(*rr)); + struct rr_mg *rr = getmem(sizeof(*rr)); - rr->mgmname = extract_name(&s, "mgmname", 0); - if (!rr->mgmname) - return NULL; - if (*s) { - return bitch("garbage after valid MG data"); - } + rr->mgmname = extract_name(&s, "mgmname", 0); + if (!rr->mgmname) + return NULL; + if (*s) { + return bitch("garbage after valid MG data"); + } - return store_record(type, name, ttl, rr); + return store_record(type, name, ttl, rr); } static char* mg_human(struct rr *rrv) { - RRCAST(mg); + RRCAST(mg); return rr->mgmname; } static struct binary_data mg_wirerdata(struct rr *rrv) { - RRCAST(mg); - return name2wire_name(rr->mgmname); + RRCAST(mg); + return name2wire_name(rr->mgmname); } struct rr_methods mg_methods = { mg_parse, mg_human, mg_wirerdata, NULL, NULL }; diff --git a/minfo.c b/minfo.c index 2ffb0ea..f585a9a 100644 --- a/minfo.c +++ b/minfo.c @@ -19,38 +19,38 @@ static struct rr *minfo_parse(char *name, long ttl, int type, char *s) { - struct rr_minfo *rr = getmem(sizeof(*rr)); + struct rr_minfo *rr = getmem(sizeof(*rr)); - rr->rmailbx = extract_name(&s, "rmailbx", 0); - if (!rr->rmailbx) - return NULL; + rr->rmailbx = extract_name(&s, "rmailbx", 0); + if (!rr->rmailbx) + return NULL; - rr->emailbx = extract_name(&s, "emailbx", 0); - if (!rr->emailbx) - return NULL; + rr->emailbx = extract_name(&s, "emailbx", 0); + if (!rr->emailbx) + return NULL; - if (*s) { - return bitch("garbage after valid MINFO data"); - } + if (*s) { + return bitch("garbage after valid MINFO data"); + } - return store_record(type, name, ttl, rr); + return store_record(type, name, ttl, rr); } static char* minfo_human(struct rr *rrv) { - RRCAST(minfo); - char s[1024]; + RRCAST(minfo); + char s[1024]; - snprintf(s, 1024, "%s %s", rr->rmailbx, rr->emailbx); - return quickstrdup_temp(s); + snprintf(s, 1024, "%s %s", rr->rmailbx, rr->emailbx); + return quickstrdup_temp(s); } static struct binary_data minfo_wirerdata(struct rr *rrv) { - RRCAST(minfo); - return compose_binary_data("dd", 1, - name2wire_name(rr->rmailbx), - name2wire_name(rr->emailbx)); + RRCAST(minfo); + return compose_binary_data("dd", 1, + name2wire_name(rr->rmailbx), + name2wire_name(rr->emailbx)); } struct rr_methods minfo_methods = { minfo_parse, minfo_human, minfo_wirerdata, NULL, NULL }; diff --git a/mr.c b/mr.c index 754aa01..b070e7b 100644 --- a/mr.c +++ b/mr.c @@ -19,28 +19,28 @@ static struct rr *mr_parse(char *name, long ttl, int type, char *s) { - struct rr_mr *rr = getmem(sizeof(*rr)); + struct rr_mr *rr = getmem(sizeof(*rr)); - rr->newname = extract_name(&s, "newname", 0); - if (!rr->newname) - return NULL; - if (*s) { - return bitch("garbage after valid MR data"); - } + rr->newname = extract_name(&s, "newname", 0); + if (!rr->newname) + return NULL; + if (*s) { + return bitch("garbage after valid MR data"); + } - return store_record(type, name, ttl, rr); + return store_record(type, name, ttl, rr); } static char* mr_human(struct rr *rrv) { - RRCAST(mr); + RRCAST(mr); return rr->newname; } static struct binary_data mr_wirerdata(struct rr *rrv) { - RRCAST(mr); - return name2wire_name(rr->newname); + RRCAST(mr); + return name2wire_name(rr->newname); } struct rr_methods mr_methods = { mr_parse, mr_human, mr_wirerdata, NULL, NULL }; diff --git a/mx.c b/mx.c index 8c873f3..c4ac571 100644 --- a/mx.c +++ b/mx.c @@ -19,59 +19,59 @@ static struct rr *mx_parse(char *name, long ttl, int type, char *s) { - struct rr_mx *rr = getmem(sizeof(*rr)); + struct rr_mx *rr = getmem(sizeof(*rr)); - rr->preference = extract_integer(&s, "MX preference", NULL); - if (rr->preference < 0) - return NULL; - /* XXX preference range check */ - rr->exchange = extract_name(&s, "MX exchange", 0); - if (!rr->exchange) - return NULL; - if (*s) { - return bitch("garbage after valid MX data"); - } + rr->preference = extract_integer(&s, "MX preference", NULL); + if (rr->preference < 0) + return NULL; + /* XXX preference range check */ + rr->exchange = extract_name(&s, "MX exchange", 0); + if (!rr->exchange) + return NULL; + if (*s) { + return bitch("garbage after valid MX data"); + } - return store_record(type, name, ttl, rr); + return store_record(type, name, ttl, rr); } static char* mx_human(struct rr *rrv) { - RRCAST(mx); + RRCAST(mx); char s[1024]; snprintf(s, 1024, "%d %s", - rr->preference, rr->exchange); + rr->preference, rr->exchange); return quickstrdup_temp(s); } static struct binary_data mx_wirerdata(struct rr *rrv) { - RRCAST(mx); + RRCAST(mx); return compose_binary_data("2d", 1, - rr->preference, name2wire_name(rr->exchange)); + rr->preference, name2wire_name(rr->exchange)); } static void* mx_validate_set(struct rr_set *rr_set) { - if (rr_set->named_rr->flags & NAME_FLAG_CONTAINS_SLASH) { - struct rr *rr = rr_set->tail; - return moan(rr->file_name, rr->line, "host name contains '/'"); - } - return NULL; + if (rr_set->named_rr->flags & NAME_FLAG_CONTAINS_SLASH) { + struct rr *rr = rr_set->tail; + return moan(rr->file_name, rr->line, "host name contains '/'"); + } + return NULL; } static void *mx_validate(struct rr *rrv) { - RRCAST(mx); + RRCAST(mx); - if (G.opt.policy_checks[POLICY_MX_ALIAS]) { - if (find_rr_set(T_CNAME, rr->exchange)) { - return moan(rr->rr.file_name, rr->rr.line, "MX exchange is an alias"); - } - } - return NULL; + if (G.opt.policy_checks[POLICY_MX_ALIAS]) { + if (find_rr_set(T_CNAME, rr->exchange)) { + return moan(rr->rr.file_name, rr->rr.line, "MX exchange is an alias"); + } + } + return NULL; } struct rr_methods mx_methods = { mx_parse, mx_human, mx_wirerdata, mx_validate_set, mx_validate }; diff --git a/naptr.c b/naptr.c index da9472a..1bdbcd5 100644 --- a/naptr.c +++ b/naptr.c @@ -20,74 +20,74 @@ static struct rr *naptr_parse(char *name, long ttl, int type, char *s) { - struct rr_naptr *rr = getmem(sizeof(*rr)); - int i; - struct binary_data text; - - i = extract_integer(&s, "order", NULL); - if (i < 0) - return NULL; - if (i >= 65536) - return bitch("order range is not valid"); - rr->order = i; - - i = extract_integer(&s, "preference", NULL); - if (i < 0) - return NULL; - if (i >= 65536) - return bitch("preference range is not valid"); - rr->preference = i; - - text = extract_text(&s, "flags"); - if (text.length < 0) - return NULL; - for (i = 0; i < text.length; i++) { - if (!isalnum(text.data[i])) { - return bitch("flags contains illegal characters"); - } - } - rr->flags = text; - - text = extract_text(&s, "services"); - if (text.length < 0) - return NULL; - rr->services = text; - - text = extract_text(&s, "regexp"); - if (text.length < 0) - return NULL; - rr->regexp = text; - - rr->replacement = extract_name(&s, "replacement", 0); - if (!rr->replacement) - return NULL; - - if (*s) { - return bitch("garbage after valid NAPTR data"); - } - - return store_record(type, name, ttl, rr); + struct rr_naptr *rr = getmem(sizeof(*rr)); + int i; + struct binary_data text; + + i = extract_integer(&s, "order", NULL); + if (i < 0) + return NULL; + if (i >= 65536) + return bitch("order range is not valid"); + rr->order = i; + + i = extract_integer(&s, "preference", NULL); + if (i < 0) + return NULL; + if (i >= 65536) + return bitch("preference range is not valid"); + rr->preference = i; + + text = extract_text(&s, "flags"); + if (text.length < 0) + return NULL; + for (i = 0; i < text.length; i++) { + if (!isalnum(text.data[i])) { + return bitch("flags contains illegal characters"); + } + } + rr->flags = text; + + text = extract_text(&s, "services"); + if (text.length < 0) + return NULL; + rr->services = text; + + text = extract_text(&s, "regexp"); + if (text.length < 0) + return NULL; + rr->regexp = text; + + rr->replacement = extract_name(&s, "replacement", 0); + if (!rr->replacement) + return NULL; + + if (*s) { + return bitch("garbage after valid NAPTR data"); + } + + return store_record(type, name, ttl, rr); } static char* naptr_human(struct rr *rrv) { - RRCAST(naptr); + RRCAST(naptr); char s[1024]; - snprintf(s, 1024, "%hu %hu \"%s\" ...", - rr->order, rr->preference, rr->flags.data); + snprintf(s, 1024, "%hu %hu \"%s\" ...", + rr->order, rr->preference, rr->flags.data); - return quickstrdup_temp(s); + return quickstrdup_temp(s); } static struct binary_data naptr_wirerdata(struct rr *rrv) { - RRCAST(naptr); + RRCAST(naptr); return compose_binary_data("22bbbd", 1, - rr->order, rr->preference, - rr->flags, rr->services, rr->regexp, - name2wire_name(rr->replacement)); + rr->order, rr->preference, + rr->flags, rr->services, rr->regexp, + name2wire_name(rr->replacement)); } struct rr_methods naptr_methods = { naptr_parse, naptr_human, naptr_wirerdata, NULL, NULL }; diff --git a/nid.c b/nid.c index 3d0e030..763185d 100644 --- a/nid.c +++ b/nid.c @@ -19,39 +19,39 @@ static struct rr *nid_parse(char *name, long ttl, int type, char *s) { - struct rr_nid *rr = getmem(sizeof(*rr)); - int preference; + struct rr_nid *rr = getmem(sizeof(*rr)); + int preference; - rr->preference = preference = extract_integer(&s, "NID preference", NULL); - if (preference < 0) - return NULL; - if (extract_u64(&s, "NodeID", &rr->node_id) < 0) - return NULL; + rr->preference = preference = extract_integer(&s, "NID preference", NULL); + if (preference < 0) + return NULL; + if (extract_u64(&s, "NodeID", &rr->node_id) < 0) + return NULL; - if (*s) { - return bitch("garbage after valid NID data"); - } + if (*s) { + return bitch("garbage after valid NID data"); + } - return store_record(type, name, ttl, rr); + return store_record(type, name, ttl, rr); } static char* nid_human(struct rr *rrv) { - RRCAST(nid); + RRCAST(nid); char s[1024]; snprintf(s, 1024, "%d %x:%x:%x:%x", - rr->preference, - (unsigned)(rr->node_id >> 48) & 0xffff, - (unsigned)(rr->node_id >> 32) & 0xffff, - (unsigned)(rr->node_id >> 16) & 0xffff, - (unsigned)(rr->node_id >> 0) & 0xffff); + rr->preference, + (unsigned)(rr->node_id >> 48) & 0xffff, + (unsigned)(rr->node_id >> 32) & 0xffff, + (unsigned)(rr->node_id >> 16) & 0xffff, + (unsigned)(rr->node_id >> 0) & 0xffff); return quickstrdup_temp(s); } static struct binary_data nid_wirerdata(struct rr *rrv) { - RRCAST(nid); + RRCAST(nid); return compose_binary_data("28", 1, rr->preference, rr->node_id); } diff --git a/ns.c b/ns.c index d58d297..7107045 100644 --- a/ns.c +++ b/ns.c @@ -20,63 +20,63 @@ static struct rr *ns_parse(char *name, long ttl, int type, char *s) { - struct rr_ns *rr = getmem(sizeof(*rr)); - struct rr *ret_rr; + struct rr_ns *rr = getmem(sizeof(*rr)); + struct rr *ret_rr; - rr->nsdname = extract_name(&s, "name server domain name", 0); - if (!rr->nsdname) - return NULL; - if (*s) { - return bitch("garbage after valid NS data"); - } + rr->nsdname = extract_name(&s, "name server domain name", 0); + if (!rr->nsdname) + return NULL; + if (*s) { + return bitch("garbage after valid NS data"); + } - ret_rr = store_record(type, name, ttl, rr); - if (ret_rr) { - if (!(ret_rr->rr_set->named_rr->flags & (NAME_FLAG_APEX|NAME_FLAG_DELEGATION))) { - ret_rr->rr_set->named_rr->flags |= NAME_FLAG_DELEGATION; - G.stats.delegations++; - } - } - return ret_rr; + ret_rr = store_record(type, name, ttl, rr); + if (ret_rr) { + if (!(ret_rr->rr_set->named_rr->flags & (NAME_FLAG_APEX|NAME_FLAG_DELEGATION))) { + ret_rr->rr_set->named_rr->flags |= NAME_FLAG_DELEGATION; + G.stats.delegations++; + } + } + return ret_rr; } static char* ns_human(struct rr *rrv) { - RRCAST(ns); + RRCAST(ns); return rr->nsdname; } static struct binary_data ns_wirerdata(struct rr *rrv) { - RRCAST(ns); - return name2wire_name(rr->nsdname); + RRCAST(ns); + return name2wire_name(rr->nsdname); } static void* ns_validate_set(struct rr_set *rr_set) { - struct rr *rr; - if (G.opt.policy_checks[POLICY_SINGLE_NS]) { - if (rr_set->count < 2) { - rr = rr_set->tail; - return moan(rr->file_name, rr->line, "there should be at least two NS records per name"); - } - } - return NULL; + struct rr *rr; + if (G.opt.policy_checks[POLICY_SINGLE_NS]) { + if (rr_set->count < 2) { + rr = rr_set->tail; + return moan(rr->file_name, rr->line, "there should be at least two NS records per name"); + } + } + return NULL; } static void *ns_validate(struct rr *rrv) { - RRCAST(ns); + RRCAST(ns); - if (G.opt.policy_checks[POLICY_NS_ALIAS]) { - if (find_rr_set(T_CNAME, rr->nsdname)) { - return moan(rr->rr.file_name, rr->rr.line, "NS data is an alias"); - } - } - if (strchr(rr->nsdname, '/') != NULL) - return moan(rr->rr.file_name, rr->rr.line, "NS data contains '/'"); - return NULL; + if (G.opt.policy_checks[POLICY_NS_ALIAS]) { + if (find_rr_set(T_CNAME, rr->nsdname)) { + return moan(rr->rr.file_name, rr->rr.line, "NS data is an alias"); + } + } + if (strchr(rr->nsdname, '/') != NULL) + return moan(rr->rr.file_name, rr->rr.line, "NS data contains '/'"); + return NULL; } struct rr_methods ns_methods = { ns_parse, ns_human, ns_wirerdata, ns_validate_set, ns_validate }; diff --git a/nsap.c b/nsap.c index 4b99493..7fc8761 100644 --- a/nsap.c +++ b/nsap.c @@ -19,15 +19,15 @@ static struct rr* nsap_parse(char *name, long ttl, int type, char *s) { - struct rr_nsap *rr = getmem(sizeof(*rr)); + struct rr_nsap *rr = getmem(sizeof(*rr)); - rr->data = extract_hex_binary_data(&s, "NSAP data", EXTRACT_EAT_WHITESPACE); - if (rr->data.length < 0) return NULL; + rr->data = extract_hex_binary_data(&s, "NSAP data", EXTRACT_EAT_WHITESPACE); + if (rr->data.length < 0) return NULL; - if (*s) { - return bitch("garbage after valid NSAP data"); - } - return store_record(type, name, ttl, rr); + if (*s) { + return bitch("garbage after valid NSAP data"); + } + return store_record(type, name, ttl, rr); } static char* nsap_human(struct rr *rrv) @@ -37,9 +37,9 @@ static char* nsap_human(struct rr *rrv) static struct binary_data nsap_wirerdata(struct rr *rrv) { - RRCAST(nsap); + RRCAST(nsap); - return compose_binary_data("d", 1, rr->data); + return compose_binary_data("d", 1, rr->data); } struct rr_methods nsap_methods = { nsap_parse, nsap_human, nsap_wirerdata, NULL, NULL }; diff --git a/nsec.c b/nsec.c index 83b4e10..892fcbf 100644 --- a/nsec.c +++ b/nsec.c @@ -1,18 +1,18 @@ /* * Part of DNS zone file validator `validns`. - 604800 NSEC example.com. NS DS RRSIG NSEC - 604800 RRSIG NSEC 10 3 604800 20130321184221 ( - 20130219184221 35615 example.com. - WWg7EiYoY8Hp593I2i5Mkl2ezg7YuAnq0y75 - oymTCuEfGwh4OxbMT/mWNqAFL5Y8f0YoQOOY - wZP0m/sGK/EJN7ulNsfQyULY4WsyHIGlKMwT - KdyDXJLrmrzlmRnGv7pFb0bo53n3osE0uFfH - yMQYOkQRYfqa4yWXF9Nl48dy67frtVih0foy - 9Mm76mmJSDUd/jGsYQmaoFGVU/a64rWapVQ9 - O/mXPqr6Pw2ZCHecsF4ElMEp41YqG1DfR5QR - khTjvTlg4aTKvgX1YuvDhjUygSHit47xn2NC - 2WwEZF+vYXT9DIUCMcKdVeb4bjWwUXbWNFqz - Ca3jb/mpOpUDFnrRPw== ) + 604800 NSEC example.com. NS DS RRSIG NSEC + 604800 RRSIG NSEC 10 3 604800 20130321184221 ( + 20130219184221 35615 example.com. + WWg7EiYoY8Hp593I2i5Mkl2ezg7YuAnq0y75 + oymTCuEfGwh4OxbMT/mWNqAFL5Y8f0YoQOOY + wZP0m/sGK/EJN7ulNsfQyULY4WsyHIGlKMwT + KdyDXJLrmrzlmRnGv7pFb0bo53n3osE0uFfH + yMQYOkQRYfqa4yWXF9Nl48dy67frtVih0foy + 9Mm76mmJSDUd/jGsYQmaoFGVU/a64rWapVQ9 + O/mXPqr6Pw2ZCHecsF4ElMEp41YqG1DfR5QR + khTjvTlg4aTKvgX1YuvDhjUygSHit47xn2NC + 2WwEZF+vYXT9DIUCMcKdVeb4bjWwUXbWNFqz + Ca3jb/mpOpUDFnrRPw== ) * * Copyright 2011-2014 Anton Berezin * Modified BSD license. @@ -35,114 +35,114 @@ static struct rr* nsec_parse(char *name, long ttl, int type, char *s) { struct rr_nsec *rr = getmem(sizeof(*rr)); - struct binary_data bitmap; - char *str_type = NULL; - int ltype; + struct binary_data bitmap; + char *str_type = NULL; + int ltype; rr->next_domain = extract_name(&s, "next domain", KEEP_CAPITALIZATION); - /* TODO: validate next_domain, http://tools.ietf.org/html/rfc4034#section-4.1.1 */ - - bitmap = new_set(); - while (s && *s) { - str_type = extract_label(&s, "type list", "temporary"); - if (!str_type) return NULL; - ltype = str2rdtype(str_type, NULL); - if (ltype < 0) - return NULL; - add_bit_to_set(&bitmap, ltype); - } - if (!s) - return NULL; - if (!str_type) { - return bitch("NSEC type list should not be empty"); - } - rr->type_bitmap = compressed_set(&bitmap); - G.dnssec_active = 1; + /* TODO: validate next_domain, http://tools.ietf.org/html/rfc4034#section-4.1.1 */ + + bitmap = new_set(); + while (s && *s) { + str_type = extract_label(&s, "type list", "temporary"); + if (!str_type) return NULL; + ltype = str2rdtype(str_type, NULL); + if (ltype < 0) + return NULL; + add_bit_to_set(&bitmap, ltype); + } + if (!s) + return NULL; + if (!str_type) { + return bitch("NSEC type list should not be empty"); + } + rr->type_bitmap = compressed_set(&bitmap); + G.dnssec_active = 1; return store_record(type, name, ttl, rr); } static char* nsec_human(struct rr *rrv) { - RRCAST(nsec); + RRCAST(nsec); char ss[1024]; - char *s = ss; - int l; - char *base; - int i, k; - int type; - char *type_name; + char *s = ss; + int l; + char *base; + int i, k; + int type; + char *type_name; l = snprintf(s, 1024, "%s", rr->next_domain); - s += l; - base = rr->type_bitmap.data; - while (base - rr->type_bitmap.data < rr->type_bitmap.length) { - for (i = 0; i < base[1]; i++) { - for (k = 0; k <= 7; k++) { - if (base[2+i] & (0x80 >> k)) { - type = ((unsigned char)base[0])*256 + i*8 + k; - type_name = rdtype2str(type); - l = snprintf(s, 1024-(s-ss), " %s", type_name); - s += l; - } - } - } - base += base[1]+2; - } + s += l; + base = rr->type_bitmap.data; + while (base - rr->type_bitmap.data < rr->type_bitmap.length) { + for (i = 0; i < base[1]; i++) { + for (k = 0; k <= 7; k++) { + if (base[2+i] & (0x80 >> k)) { + type = ((unsigned char)base[0])*256 + i*8 + k; + type_name = rdtype2str(type); + l = snprintf(s, 1024-(s-ss), " %s", type_name); + s += l; + } + } + } + base += base[1]+2; + } return quickstrdup_temp(ss); } static struct binary_data nsec_wirerdata(struct rr *rrv) { - RRCAST(nsec); + RRCAST(nsec); - return compose_binary_data("dd", 1, - name2wire_name(rr->next_domain), rr->type_bitmap); + return compose_binary_data("dd", 1, + name2wire_name(rr->next_domain), rr->type_bitmap); } static void* nsec_validate(struct rr *rrv) { - RRCAST(nsec); - struct named_rr *named_rr; + RRCAST(nsec); + struct named_rr *named_rr; - named_rr = rr->rr.rr_set->named_rr; - if (!check_typemap(rr->type_bitmap, named_rr, rrv)) - return NULL; + named_rr = rr->rr.rr_set->named_rr; + if (!check_typemap(rr->type_bitmap, named_rr, rrv)) + return NULL; - return rr; + return rr; } void validate_nsec_chain(void) { - struct rr_set *rr_set; - struct named_rr *named_rr; - - rr_set = find_rr_set(T_NSEC, zone_apex); - if (!rr_set) { - named_rr = find_named_rr(zone_apex); - moan(named_rr->file_name, named_rr->line, "apex NSEC not found"); - return; - } - while (1) { - char name[1024]; - struct rr_nsec *rr = (struct rr_nsec *)rr_set->tail; - char *s, *t; - - if (strcasecmp(rr->next_domain, zone_apex) == 0) /* chain complete */ - break; - freeall_temp(); - s = rr->next_domain; - t = name; - while (*s) *t++ = tolower(*s++); - *t = 0; - rr_set = find_rr_set(T_NSEC, name); - if (!rr_set) { - moan(rr->rr.file_name, rr->rr.line, "broken NSEC chain %s -> %s", - rr->rr.rr_set->named_rr->name, rr->next_domain); - break; - } - } - freeall_temp(); + struct rr_set *rr_set; + struct named_rr *named_rr; + + rr_set = find_rr_set(T_NSEC, zone_apex); + if (!rr_set) { + named_rr = find_named_rr(zone_apex); + moan(named_rr->file_name, named_rr->line, "apex NSEC not found"); + return; + } + while (1) { + char name[1024]; + struct rr_nsec *rr = (struct rr_nsec *)rr_set->tail; + char *s, *t; + + if (strcasecmp(rr->next_domain, zone_apex) == 0) /* chain complete */ + break; + freeall_temp(); + s = rr->next_domain; + t = name; + while (*s) *t++ = tolower(*s++); + *t = 0; + rr_set = find_rr_set(T_NSEC, name); + if (!rr_set) { + moan(rr->rr.file_name, rr->rr.line, "broken NSEC chain %s -> %s", + rr->rr.rr_set->named_rr->name, rr->next_domain); + break; + } + } + freeall_temp(); } struct rr_methods nsec_methods = { nsec_parse, nsec_human, nsec_wirerdata, NULL, nsec_validate }; diff --git a/nsec3.c b/nsec3.c index c2440fa..2416071 100644 --- a/nsec3.c +++ b/nsec3.c @@ -24,125 +24,125 @@ static struct rr* nsec3_parse(char *name, long ttl, int type, char *s) { struct rr_nsec3 *rr = getmem(sizeof(*rr)); - struct rr *ret_rr; - struct binary_data bitmap; - int i; - int opt_out = 0; - char *str_type = NULL; - int ltype; - - i = extract_integer(&s, "hash algorithm", NULL); - if (i < 0) - return NULL; - if (i > 255) - return bitch("bad hash algorithm value"); - if (i != 1) - return bitch("unrecognized or unsupported hash algorithm"); - rr->hash_algorithm = i; - - i = extract_integer(&s, "flags", NULL); - if (i < 0) - return NULL; - if (i > 255) - return bitch("bad flags value"); - - if (!(i == 0 || i == 1)) - return bitch("unsupported flags value"); - if (i == 1) - opt_out = 1; - rr->flags = i; - - i = extract_integer(&s, "iterations", NULL); - if (i < 0) - return NULL; - if (i > 2500) - return bitch("bad iterations value"); - rr->iterations = i; - /* TODO validate iteration count according to key size, - * as per http://tools.ietf.org/html/rfc5155#section-10.3 */ - - if (*s == '-') { - rr->salt.length = 0; - rr->salt.data = NULL; - s++; - if (*s && !isspace(*s) && *s != ';' && *s != ')') - return bitch("salt is not valid"); - s = skip_white_space(s); - } else { - rr->salt = extract_hex_binary_data(&s, "salt", EXTRACT_DONT_EAT_WHITESPACE); - if (rr->salt.length <= 0) - return NULL; - if (rr->salt.length > 255) - return bitch("salt is too long"); - } - - rr->next_hashed_owner = extract_base32hex_binary_data(&s, "next hashed owner"); - if (rr->next_hashed_owner.length != 20) { - return bitch("next hashed owner does not have the right size"); - } - - bitmap = new_set(); - while (s && *s) { - str_type = extract_label(&s, "type list", "temporary"); - if (!str_type) return NULL; - ltype = str2rdtype(str_type, NULL); - if (ltype < 0) - return NULL; - add_bit_to_set(&bitmap, ltype); - } - if (!s) - return NULL; - rr->type_bitmap = compressed_set(&bitmap); - - rr->corresponding_name = NULL; - rr->next_nsec3 = NULL; - - if (!remember_nsec3(name, rr)) - return NULL; + struct rr *ret_rr; + struct binary_data bitmap; + int i; + int opt_out = 0; + char *str_type = NULL; + int ltype; + + i = extract_integer(&s, "hash algorithm", NULL); + if (i < 0) + return NULL; + if (i > 255) + return bitch("bad hash algorithm value"); + if (i != 1) + return bitch("unrecognized or unsupported hash algorithm"); + rr->hash_algorithm = i; + + i = extract_integer(&s, "flags", NULL); + if (i < 0) + return NULL; + if (i > 255) + return bitch("bad flags value"); + + if (!(i == 0 || i == 1)) + return bitch("unsupported flags value"); + if (i == 1) + opt_out = 1; + rr->flags = i; + + i = extract_integer(&s, "iterations", NULL); + if (i < 0) + return NULL; + if (i > 2500) + return bitch("bad iterations value"); + rr->iterations = i; + /* TODO validate iteration count according to key size, + * as per http://tools.ietf.org/html/rfc5155#section-10.3 */ + + if (*s == '-') { + rr->salt.length = 0; + rr->salt.data = NULL; + s++; + if (*s && !isspace(*s) && *s != ';' && *s != ')') + return bitch("salt is not valid"); + s = skip_white_space(s); + } else { + rr->salt = extract_hex_binary_data(&s, "salt", EXTRACT_DONT_EAT_WHITESPACE); + if (rr->salt.length <= 0) + return NULL; + if (rr->salt.length > 255) + return bitch("salt is too long"); + } + + rr->next_hashed_owner = extract_base32hex_binary_data(&s, "next hashed owner"); + if (rr->next_hashed_owner.length != 20) { + return bitch("next hashed owner does not have the right size"); + } + + bitmap = new_set(); + while (s && *s) { + str_type = extract_label(&s, "type list", "temporary"); + if (!str_type) return NULL; + ltype = str2rdtype(str_type, NULL); + if (ltype < 0) + return NULL; + add_bit_to_set(&bitmap, ltype); + } + if (!s) + return NULL; + rr->type_bitmap = compressed_set(&bitmap); + + rr->corresponding_name = NULL; + rr->next_nsec3 = NULL; + + if (!remember_nsec3(name, rr)) + return NULL; ret_rr = store_record(type, name, ttl, rr); - if (ret_rr) { - G.nsec3_present = 1; - G.dnssec_active = 1; - G.stats.nsec3_count++; - if (opt_out) { - G.nsec3_opt_out_present = 1; - } - if (ret_rr && !nsec3param) - nsec3param = ret_rr; - } - return ret_rr; + if (ret_rr) { + G.nsec3_present = 1; + G.dnssec_active = 1; + G.stats.nsec3_count++; + if (opt_out) { + G.nsec3_opt_out_present = 1; + } + if (ret_rr && !nsec3param) + nsec3param = ret_rr; + } + return ret_rr; } static char* nsec3_human(struct rr *rrv) { - RRCAST(nsec3); + RRCAST(nsec3); char ss[1024]; - char *s = ss; - int l; - int i; + char *s = ss; + int l; + int i; l = snprintf(s, 1024, "%u %u %u ", rr->hash_algorithm, rr->flags, rr->iterations); - s += l; - if (rr->salt.length) { - for (i = 0; i < rr->salt.length; i++) { - l = snprintf(s, 1024-(s-ss), "%02X", (unsigned char)rr->salt.data[i]); - s += l; - } - } else { - sprintf(s, "-"); - } + s += l; + if (rr->salt.length) { + for (i = 0; i < rr->salt.length; i++) { + l = snprintf(s, 1024-(s-ss), "%02X", (unsigned char)rr->salt.data[i]); + s += l; + } + } else { + sprintf(s, "-"); + } return quickstrdup_temp(ss); } static struct binary_data nsec3_wirerdata(struct rr *rrv) { - RRCAST(nsec3); + RRCAST(nsec3); - return compose_binary_data("112bbd", 1, - rr->hash_algorithm, rr->flags, - rr->iterations, rr->salt, - rr->next_hashed_owner, rr->type_bitmap); + return compose_binary_data("112bbd", 1, + rr->hash_algorithm, rr->flags, + rr->iterations, rr->salt, + rr->next_hashed_owner, rr->type_bitmap); } struct rr_nsec3 *first_nsec3 = NULL; @@ -150,36 +150,36 @@ struct rr_nsec3 *latest_nsec3 = NULL; void* nsec3_validate(struct rr *rrv) { - RRCAST(nsec3); - - if (!first_nsec3) { - first_nsec3 = rr; - } - if (latest_nsec3) { - if (memcmp(latest_nsec3->next_hashed_owner.data, rr->this_hashed_name.data, 20) != 0) { - char *expected_name = quickstrdup_temp(rr->rr.rr_set->named_rr->name); - /* guaranteed to have same length, I think */ - encode_base32hex(expected_name, 32, latest_nsec3->next_hashed_owner.data, 20); - if (rr == first_nsec3) { - moan(latest_nsec3->rr.file_name, latest_nsec3->rr.line, - "broken NSEC3 chain, expected %s, but nothing found", - expected_name); - } else { - moan(latest_nsec3->rr.file_name, latest_nsec3->rr.line, - "broken NSEC3 chain, expected %s, but found %s", - expected_name, - rr->rr.rr_set->named_rr->name); - } - if (rr != first_nsec3) - latest_nsec3->next_nsec3 = rr; - latest_nsec3 = rr; - return NULL; - } - if (rr != first_nsec3) - latest_nsec3->next_nsec3 = rr; - } - latest_nsec3 = rr; - return rr; + RRCAST(nsec3); + + if (!first_nsec3) { + first_nsec3 = rr; + } + if (latest_nsec3) { + if (memcmp(latest_nsec3->next_hashed_owner.data, rr->this_hashed_name.data, 20) != 0) { + char *expected_name = quickstrdup_temp(rr->rr.rr_set->named_rr->name); + /* guaranteed to have same length, I think */ + encode_base32hex(expected_name, 32, latest_nsec3->next_hashed_owner.data, 20); + if (rr == first_nsec3) { + moan(latest_nsec3->rr.file_name, latest_nsec3->rr.line, + "broken NSEC3 chain, expected %s, but nothing found", + expected_name); + } else { + moan(latest_nsec3->rr.file_name, latest_nsec3->rr.line, + "broken NSEC3 chain, expected %s, but found %s", + expected_name, + rr->rr.rr_set->named_rr->name); + } + if (rr != first_nsec3) + latest_nsec3->next_nsec3 = rr; + latest_nsec3 = rr; + return NULL; + } + if (rr != first_nsec3) + latest_nsec3->next_nsec3 = rr; + } + latest_nsec3 = rr; + return rr; } struct rr_methods nsec3_methods = { nsec3_parse, nsec3_human, nsec3_wirerdata, NULL, nsec3_validate }; diff --git a/nsec3checks.c b/nsec3checks.c index 69c6553..16c6f3d 100644 --- a/nsec3checks.c +++ b/nsec3checks.c @@ -28,44 +28,44 @@ static struct binary_data name2hash(char *name, struct rr *param) { struct rr_nsec3param *p = (struct rr_nsec3param *)param; - EVP_MD_CTX ctx; - unsigned char md0[EVP_MAX_MD_SIZE]; - unsigned char md1[EVP_MAX_MD_SIZE]; - unsigned char *md[2]; - int mdi = 0; - struct binary_data r = bad_binary_data(); - struct binary_data wire_name = name2wire_name(name); - int i; - int digest_size; + EVP_MD_CTX ctx; + unsigned char md0[EVP_MAX_MD_SIZE]; + unsigned char md1[EVP_MAX_MD_SIZE]; + unsigned char *md[2]; + int mdi = 0; + struct binary_data r = bad_binary_data(); + struct binary_data wire_name = name2wire_name(name); + int i; + int digest_size; - md[0] = md0; - md[1] = md1; - if (wire_name.length < 0) - return r; + md[0] = md0; + md[1] = md1; + if (wire_name.length < 0) + return r; - /* XXX Maybe use Init_ex and Final_ex for speed? */ + /* XXX Maybe use Init_ex and Final_ex for speed? */ - EVP_MD_CTX_init(&ctx); - if (EVP_DigestInit(&ctx, EVP_sha1()) != 1) - return r; - digest_size = EVP_MD_CTX_size(&ctx); - EVP_DigestUpdate(&ctx, wire_name.data, wire_name.length); - EVP_DigestUpdate(&ctx, p->salt.data, p->salt.length); - EVP_DigestFinal(&ctx, md[mdi], NULL); + EVP_MD_CTX_init(&ctx); + if (EVP_DigestInit(&ctx, EVP_sha1()) != 1) + return r; + digest_size = EVP_MD_CTX_size(&ctx); + EVP_DigestUpdate(&ctx, wire_name.data, wire_name.length); + EVP_DigestUpdate(&ctx, p->salt.data, p->salt.length); + EVP_DigestFinal(&ctx, md[mdi], NULL); - for (i = 0; i < p->iterations; i++) { - if (EVP_DigestInit(&ctx, EVP_sha1()) != 1) - return r; - EVP_DigestUpdate(&ctx, md[mdi], digest_size); - mdi = (mdi + 1) % 2; - EVP_DigestUpdate(&ctx, p->salt.data, p->salt.length); - EVP_DigestFinal(&ctx, md[mdi], NULL); - } + for (i = 0; i < p->iterations; i++) { + if (EVP_DigestInit(&ctx, EVP_sha1()) != 1) + return r; + EVP_DigestUpdate(&ctx, md[mdi], digest_size); + mdi = (mdi + 1) % 2; + EVP_DigestUpdate(&ctx, p->salt.data, p->salt.length); + EVP_DigestFinal(&ctx, md[mdi], NULL); + } - r.length = digest_size; - r.data = getmem(digest_size); - memcpy(r.data, md[mdi], digest_size); - return r; + r.length = digest_size; + r.data = getmem(digest_size); + memcpy(r.data, md[mdi], digest_size); + return r; } int sorted_hashed_names_count; @@ -76,193 +76,193 @@ void *nsec3_hash; static int validate_nsec3_for_name(const char *name, intptr_t *data, void *p) { - struct named_rr *named_rr = *((struct named_rr **)data); - struct binary_data hash; - struct rr_nsec3 **nsec3_slot; - struct rr_nsec3 *nsec3; + struct named_rr *named_rr = *((struct named_rr **)data); + struct binary_data hash; + struct rr_nsec3 **nsec3_slot; + struct rr_nsec3 *nsec3; - if ((named_rr->flags & mask) == NAME_FLAG_KIDS_WITH_RECORDS) { - //fprintf(stderr, "--- need nsec3, kids with records: %s\n", named_rr->name); + if ((named_rr->flags & mask) == NAME_FLAG_KIDS_WITH_RECORDS) { + //fprintf(stderr, "--- need nsec3, kids with records: %s\n", named_rr->name); needs_nsec3: - freeall_temp(); - hash = name2hash(named_rr->name, nsec3param); - if (hash.length < 0) { - moan(named_rr->file_name, named_rr->line, "internal: cannot calculate hashed name"); - goto next; - } - if (hash.length != 20) - croak(4, "assertion failed: wrong hashed name size %d", hash.length); - JHSG(nsec3_slot, nsec3_hash, hash.data, hash.length); - if (nsec3_slot == PJERR) - croak(5, "perform_remaining_nsec3checks: JHSG failed"); - if (!nsec3_slot) { - moan(named_rr->file_name, named_rr->line, - "no corresponding NSEC3 found for %s", - named_rr->name); - goto next; - } - nsec3 = *nsec3_slot; - if (!nsec3) - croak(6, "assertion failed: existing nsec3 from hash is empty"); - nsec3->corresponding_name = named_rr; - sorted_hashed_names_count++; - check_typemap(nsec3->type_bitmap, named_rr, &nsec3->rr); - } else if ((named_rr->flags & - (NAME_FLAG_NOT_AUTHORITATIVE|NAME_FLAG_SIGNED_DELEGATION)) == - NAME_FLAG_SIGNED_DELEGATION) - { - //fprintf(stderr, "--- need nsec3, signed delegation: %s\n", named_rr->name); - goto needs_nsec3; - } else if (!G.nsec3_opt_out_present && (named_rr->flags & - (NAME_FLAG_APEX_PARENT|NAME_FLAG_NOT_AUTHORITATIVE|NAME_FLAG_DELEGATION|NAME_FLAG_HAS_RECORDS)) == - 0) - { - //fprintf(stderr, "--- need nsec3, empty non-term: %s\n", named_rr->name); - goto needs_nsec3; - } else if (!G.nsec3_opt_out_present && (named_rr->flags & (NAME_FLAG_DELEGATION|NAME_FLAG_NOT_AUTHORITATIVE))==NAME_FLAG_DELEGATION) - { - //fprintf(stderr, "--- need nsec3, no opt-out: %s\n", named_rr->name); - goto needs_nsec3; - } else if (!G.nsec3_opt_out_present && (named_rr->flags & (NAME_FLAG_THIS_WITH_RECORDS|NAME_FLAG_NOT_AUTHORITATIVE)) == NAME_FLAG_THIS_WITH_RECORDS) - { - //fprintf(stderr, "--- need nsec3, this with records: %s\n", named_rr->name); - goto needs_nsec3; - } else { - //fprintf(stderr, "--- NO need for nsec3: %s\n", named_rr->name); - } + freeall_temp(); + hash = name2hash(named_rr->name, nsec3param); + if (hash.length < 0) { + moan(named_rr->file_name, named_rr->line, "internal: cannot calculate hashed name"); + goto next; + } + if (hash.length != 20) + croak(4, "assertion failed: wrong hashed name size %d", hash.length); + JHSG(nsec3_slot, nsec3_hash, hash.data, hash.length); + if (nsec3_slot == PJERR) + croak(5, "perform_remaining_nsec3checks: JHSG failed"); + if (!nsec3_slot) { + moan(named_rr->file_name, named_rr->line, + "no corresponding NSEC3 found for %s", + named_rr->name); + goto next; + } + nsec3 = *nsec3_slot; + if (!nsec3) + croak(6, "assertion failed: existing nsec3 from hash is empty"); + nsec3->corresponding_name = named_rr; + sorted_hashed_names_count++; + check_typemap(nsec3->type_bitmap, named_rr, &nsec3->rr); + } else if ((named_rr->flags & + (NAME_FLAG_NOT_AUTHORITATIVE|NAME_FLAG_SIGNED_DELEGATION)) == + NAME_FLAG_SIGNED_DELEGATION) + { + //fprintf(stderr, "--- need nsec3, signed delegation: %s\n", named_rr->name); + goto needs_nsec3; + } else if (!G.nsec3_opt_out_present && (named_rr->flags & + (NAME_FLAG_APEX_PARENT|NAME_FLAG_NOT_AUTHORITATIVE|NAME_FLAG_DELEGATION|NAME_FLAG_HAS_RECORDS)) == + 0) + { + //fprintf(stderr, "--- need nsec3, empty non-term: %s\n", named_rr->name); + goto needs_nsec3; + } else if (!G.nsec3_opt_out_present && (named_rr->flags & (NAME_FLAG_DELEGATION|NAME_FLAG_NOT_AUTHORITATIVE))==NAME_FLAG_DELEGATION) + { + //fprintf(stderr, "--- need nsec3, no opt-out: %s\n", named_rr->name); + goto needs_nsec3; + } else if (!G.nsec3_opt_out_present && (named_rr->flags & (NAME_FLAG_THIS_WITH_RECORDS|NAME_FLAG_NOT_AUTHORITATIVE)) == NAME_FLAG_THIS_WITH_RECORDS) + { + //fprintf(stderr, "--- need nsec3, this with records: %s\n", named_rr->name); + goto needs_nsec3; + } else { + //fprintf(stderr, "--- NO need for nsec3: %s\n", named_rr->name); + } next: - return 1; + return 1; } void perform_remaining_nsec3checks(void) { - struct rr_nsec3 *nsec3; + struct rr_nsec3 *nsec3; - sorted_hashed_names_count = 0; - mask = NAME_FLAG_NOT_AUTHORITATIVE|NAME_FLAG_NSEC3_ONLY|NAME_FLAG_KIDS_WITH_RECORDS; - if (G.nsec3_opt_out_present) { - mask |= NAME_FLAG_DELEGATION; - } + sorted_hashed_names_count = 0; + mask = NAME_FLAG_NOT_AUTHORITATIVE|NAME_FLAG_NSEC3_ONLY|NAME_FLAG_KIDS_WITH_RECORDS; + if (G.nsec3_opt_out_present) { + mask |= NAME_FLAG_DELEGATION; + } - cbtree_allprefixed(&zone_data, "", validate_nsec3_for_name, NULL); + cbtree_allprefixed(&zone_data, "", validate_nsec3_for_name, NULL); - nsec3 = first_nsec3; - while (nsec3) { - if (!nsec3->corresponding_name) { - moan(nsec3->rr.file_name, nsec3->rr.line, - "NSEC3 without a corresponding record (or empty non-terminal)"); - } - nsec3 = nsec3->next_nsec3; - } + nsec3 = first_nsec3; + while (nsec3) { + if (!nsec3->corresponding_name) { + moan(nsec3->rr.file_name, nsec3->rr.line, + "NSEC3 without a corresponding record (or empty non-terminal)"); + } + nsec3 = nsec3->next_nsec3; + } } void *remember_nsec3(char *name, struct rr_nsec3 *rr) { - char hashed_name[33]; - char binary_hashed_name[20]; - int l; - struct rr_nsec3 **nsec3_slot; + char hashed_name[33]; + char binary_hashed_name[20]; + int l; + struct rr_nsec3 **nsec3_slot; - l = strlen(name); - if (l < 33 || name[32] != '.') - return bitch("NSEC3 record name is not valid"); - if (l == 33 && zone_apex_l != 1) /* root zone */ - return bitch("NSEC3 record name is not valid"); - if (l > 33 && strcmp(name+33, zone_apex) != 0) - return bitch("NSEC3 record name is not valid"); + l = strlen(name); + if (l < 33 || name[32] != '.') + return bitch("NSEC3 record name is not valid"); + if (l == 33 && zone_apex_l != 1) /* root zone */ + return bitch("NSEC3 record name is not valid"); + if (l > 33 && strcmp(name+33, zone_apex) != 0) + return bitch("NSEC3 record name is not valid"); - memcpy(hashed_name, name, 32); hashed_name[32] = 0; - l = decode_base32hex(binary_hashed_name, hashed_name, 20); - if (l != 20) - return bitch("NSEC3 record name is not valid"); - JHSI(nsec3_slot, nsec3_hash, binary_hashed_name, 20); - if (nsec3_slot == PJERR) - croak(2, "remember_nsec3: JHSI failed"); - if (*nsec3_slot) - return bitch("multiple NSEC3 with the same record name"); - *nsec3_slot = rr; - rr->this_hashed_name.length = 20; - rr->this_hashed_name.data = getmem(20); - memcpy(rr->this_hashed_name.data, binary_hashed_name, 20); - return rr; + memcpy(hashed_name, name, 32); hashed_name[32] = 0; + l = decode_base32hex(binary_hashed_name, hashed_name, 20); + if (l != 20) + return bitch("NSEC3 record name is not valid"); + JHSI(nsec3_slot, nsec3_hash, binary_hashed_name, 20); + if (nsec3_slot == PJERR) + croak(2, "remember_nsec3: JHSI failed"); + if (*nsec3_slot) + return bitch("multiple NSEC3 with the same record name"); + *nsec3_slot = rr; + rr->this_hashed_name.length = 20; + rr->this_hashed_name.data = getmem(20); + memcpy(rr->this_hashed_name.data, binary_hashed_name, 20); + return rr; } void *check_typemap(struct binary_data type_bitmap, struct named_rr *named_rr, struct rr *reference_rr) { - int type; - char *base; - int i, k; - struct rr_set *set; - uint32_t nsec_distinct_types = 0; - uint32_t real_distinct_types; + int type; + char *base; + int i, k; + struct rr_set *set; + uint32_t nsec_distinct_types = 0; + uint32_t real_distinct_types; - base = type_bitmap.data; - while (base - type_bitmap.data < type_bitmap.length) { - for (i = 0; i < base[1]; i++) { - for (k = 0; k <= 7; k++) { - if (base[2+i] & (0x80 >> k)) { - type = ((unsigned char)base[0])*256 + i*8 + k; - nsec_distinct_types++; - set = find_rr_set_in_named_rr(named_rr, type); - if (!set) { - return moan(reference_rr->file_name, reference_rr->line, - "%s mentions %s, but no such record found for %s", - rdtype2str(reference_rr->rdtype), rdtype2str(type), named_rr->name); - } - } - } - } - base += base[1]+2; - } - real_distinct_types = get_rr_set_count(named_rr); - if (real_distinct_types > nsec_distinct_types) { - void *bitmap = NULL; - struct rr_set **rr_set_slot; - int rc; - Word_t rcw; - Word_t rdtype; - int skipped = 0; + base = type_bitmap.data; + while (base - type_bitmap.data < type_bitmap.length) { + for (i = 0; i < base[1]; i++) { + for (k = 0; k <= 7; k++) { + if (base[2+i] & (0x80 >> k)) { + type = ((unsigned char)base[0])*256 + i*8 + k; + nsec_distinct_types++; + set = find_rr_set_in_named_rr(named_rr, type); + if (!set) { + return moan(reference_rr->file_name, reference_rr->line, + "%s mentions %s, but no such record found for %s", + rdtype2str(reference_rr->rdtype), rdtype2str(type), named_rr->name); + } + } + } + } + base += base[1]+2; + } + real_distinct_types = get_rr_set_count(named_rr); + if (real_distinct_types > nsec_distinct_types) { + void *bitmap = NULL; + struct rr_set **rr_set_slot; + int rc; + Word_t rcw; + Word_t rdtype; + int skipped = 0; - base = type_bitmap.data; - while (base - type_bitmap.data < type_bitmap.length) { - for (i = 0; i < base[1]; i++) { - for (k = 0; k <= 7; k++) { - if (base[2+i] & (0x80 >> k)) { - type = ((unsigned char)base[0])*256 + i*8 + k; - J1S(rc, bitmap, type); - } - } - } - base += base[1]+2; - } - rdtype = 0; - JLF(rr_set_slot, named_rr->rr_sets, rdtype); - while (rr_set_slot) { - J1T(rc, bitmap, (*rr_set_slot)->rdtype); - if (!rc) { - if ((named_rr->flags & NAME_FLAG_DELEGATION) && - ((*rr_set_slot)->rdtype == T_A || - (*rr_set_slot)->rdtype == T_AAAA)) - { - skipped++; - } else { - moan(reference_rr->file_name, reference_rr->line, - "%s exists, but %s does not mention it for %s", - rdtype2str((*rr_set_slot)->rdtype), - rdtype2str(reference_rr->rdtype), - named_rr->name); - J1FA(rcw, bitmap); - return NULL; - } - } - JLN(rr_set_slot, named_rr->rr_sets, rdtype); - } - J1FA(rcw, bitmap); - if (real_distinct_types - skipped > nsec_distinct_types) { - return moan(reference_rr->file_name, reference_rr->line, - "internal: we know %s typemap is wrong, but don't know any details", - rdtype2str(reference_rr->rdtype)); - } - } - return reference_rr; + base = type_bitmap.data; + while (base - type_bitmap.data < type_bitmap.length) { + for (i = 0; i < base[1]; i++) { + for (k = 0; k <= 7; k++) { + if (base[2+i] & (0x80 >> k)) { + type = ((unsigned char)base[0])*256 + i*8 + k; + J1S(rc, bitmap, type); + } + } + } + base += base[1]+2; + } + rdtype = 0; + JLF(rr_set_slot, named_rr->rr_sets, rdtype); + while (rr_set_slot) { + J1T(rc, bitmap, (*rr_set_slot)->rdtype); + if (!rc) { + if ((named_rr->flags & NAME_FLAG_DELEGATION) && + ((*rr_set_slot)->rdtype == T_A || + (*rr_set_slot)->rdtype == T_AAAA)) + { + skipped++; + } else { + moan(reference_rr->file_name, reference_rr->line, + "%s exists, but %s does not mention it for %s", + rdtype2str((*rr_set_slot)->rdtype), + rdtype2str(reference_rr->rdtype), + named_rr->name); + J1FA(rcw, bitmap); + return NULL; + } + } + JLN(rr_set_slot, named_rr->rr_sets, rdtype); + } + J1FA(rcw, bitmap); + if (real_distinct_types - skipped > nsec_distinct_types) { + return moan(reference_rr->file_name, reference_rr->line, + "internal: we know %s typemap is wrong, but don't know any details", + rdtype2str(reference_rr->rdtype)); + } + } + return reference_rr; } diff --git a/nsec3param.c b/nsec3param.c index 72eb48f..dbca79b 100644 --- a/nsec3param.c +++ b/nsec3param.c @@ -24,94 +24,94 @@ struct rr *nsec3param = NULL; static struct rr* nsec3param_parse(char *name, long ttl, int type, char *s) { struct rr_nsec3param *rr = getmem(sizeof(*rr)); - struct rr *ret_rr; - int i; + struct rr *ret_rr; + int i; - i = extract_integer(&s, "hash algorithm", NULL); - if (i < 0) - return NULL; - if (i > 255) - return bitch("bad hash algorithm value"); - if (i != 1) - return bitch("unrecognized or unsupported hash algorithm"); - rr->hash_algorithm = i; + i = extract_integer(&s, "hash algorithm", NULL); + if (i < 0) + return NULL; + if (i > 255) + return bitch("bad hash algorithm value"); + if (i != 1) + return bitch("unrecognized or unsupported hash algorithm"); + rr->hash_algorithm = i; - i = extract_integer(&s, "flags", NULL); - if (i < 0) - return NULL; - if (i > 255) - return bitch("bad flags value"); - if (i != 0) - return bitch("flags is supposed to be 0 for NSEC3PARAM"); - rr->flags = i; + i = extract_integer(&s, "flags", NULL); + if (i < 0) + return NULL; + if (i > 255) + return bitch("bad flags value"); + if (i != 0) + return bitch("flags is supposed to be 0 for NSEC3PARAM"); + rr->flags = i; - i = extract_integer(&s, "iterations", NULL); - if (i < 0) - return NULL; - if (i > 2500) - return bitch("bad iterations value"); - rr->iterations = i; - /* TODO validate iteration count according to key size, - * as per http://tools.ietf.org/html/rfc5155#section-10.3 */ + i = extract_integer(&s, "iterations", NULL); + if (i < 0) + return NULL; + if (i > 2500) + return bitch("bad iterations value"); + rr->iterations = i; + /* TODO validate iteration count according to key size, + * as per http://tools.ietf.org/html/rfc5155#section-10.3 */ - if (*s == '-') { - rr->salt.length = 0; - rr->salt.data = NULL; - s++; - if (*s && !isspace(*s) && *s != ';' && *s != ')') - return bitch("salt is not valid"); - s = skip_white_space(s); - } else { - rr->salt = extract_hex_binary_data(&s, "salt", EXTRACT_DONT_EAT_WHITESPACE); - if (rr->salt.length <= 0) - return NULL; - if (rr->salt.length > 255) - return bitch("salt is too long"); - } - if (*s) { - return bitch("garbage after valid NSEC3PARAM data"); - } + if (*s == '-') { + rr->salt.length = 0; + rr->salt.data = NULL; + s++; + if (*s && !isspace(*s) && *s != ';' && *s != ')') + return bitch("salt is not valid"); + s = skip_white_space(s); + } else { + rr->salt = extract_hex_binary_data(&s, "salt", EXTRACT_DONT_EAT_WHITESPACE); + if (rr->salt.length <= 0) + return NULL; + if (rr->salt.length > 255) + return bitch("salt is too long"); + } + if (*s) { + return bitch("garbage after valid NSEC3PARAM data"); + } - G.dnssec_active = 1; + G.dnssec_active = 1; ret_rr = store_record(type, name, ttl, rr); - if (ret_rr && !nsec3param && (ret_rr->rr_set->named_rr->flags & NAME_FLAG_APEX)) - nsec3param = ret_rr; - if (G.opt.policy_checks[POLICY_NSEC3PARAM_NOT_APEX] && - (ret_rr->rr_set->named_rr->flags & NAME_FLAG_APEX) == 0) - { - return bitch("NSEC3PARAM found not at zone apex"); - } - return ret_rr; + if (ret_rr && !nsec3param && (ret_rr->rr_set->named_rr->flags & NAME_FLAG_APEX)) + nsec3param = ret_rr; + if (G.opt.policy_checks[POLICY_NSEC3PARAM_NOT_APEX] && + (ret_rr->rr_set->named_rr->flags & NAME_FLAG_APEX) == 0) + { + return bitch("NSEC3PARAM found not at zone apex"); + } + return ret_rr; } static char* nsec3param_human(struct rr *rrv) { - RRCAST(nsec3param); + RRCAST(nsec3param); char ss[1024]; - char *s = ss; - int l; - int i; + char *s = ss; + int l; + int i; l = snprintf(s, 1024, "%u %u %u ", rr->hash_algorithm, rr->flags, rr->iterations); - s += l; - if (rr->salt.length) { - for (i = 0; i < rr->salt.length; i++) { - l = snprintf(s, 1024-(s-ss), "%02X", (unsigned char)rr->salt.data[i]); - s += l; - } - } else { - sprintf(s, "-"); - } + s += l; + if (rr->salt.length) { + for (i = 0; i < rr->salt.length; i++) { + l = snprintf(s, 1024-(s-ss), "%02X", (unsigned char)rr->salt.data[i]); + s += l; + } + } else { + sprintf(s, "-"); + } return quickstrdup_temp(ss); } static struct binary_data nsec3param_wirerdata(struct rr *rrv) { - RRCAST(nsec3param); + RRCAST(nsec3param); - return compose_binary_data("112b", 1, - rr->hash_algorithm, rr->flags, - rr->iterations, rr->salt); + return compose_binary_data("112b", 1, + rr->hash_algorithm, rr->flags, + rr->iterations, rr->salt); } struct rr_methods nsec3param_methods = { nsec3param_parse, nsec3param_human, nsec3param_wirerdata, NULL, NULL }; diff --git a/ptr.c b/ptr.c index 60d5559..348ed75 100644 --- a/ptr.c +++ b/ptr.c @@ -19,29 +19,29 @@ static struct rr *ptr_parse(char *name, long ttl, int type, char *s) { - struct rr_ptr *rr = getmem(sizeof(*rr)); + struct rr_ptr *rr = getmem(sizeof(*rr)); - rr->ptrdname = extract_name(&s, "name server domain name", 0); - if (!rr->ptrdname) - return NULL; - if (*s) { - return bitch("garbage after valid PTR data"); - } + rr->ptrdname = extract_name(&s, "name server domain name", 0); + if (!rr->ptrdname) + return NULL; + if (*s) { + return bitch("garbage after valid PTR data"); + } - return store_record(type, name, ttl, rr); + return store_record(type, name, ttl, rr); } static char* ptr_human(struct rr *rrv) { - RRCAST(ptr); + RRCAST(ptr); return rr->ptrdname; } static struct binary_data ptr_wirerdata(struct rr *rrv) { - RRCAST(ptr); - return name2wire_name(rr->ptrdname); + RRCAST(ptr); + return name2wire_name(rr->ptrdname); } struct rr_methods ptr_methods = { ptr_parse, ptr_human, ptr_wirerdata, NULL, NULL }; diff --git a/px.c b/px.c index 0c8aaca..624337e 100644 --- a/px.c +++ b/px.c @@ -19,45 +19,45 @@ static struct rr *px_parse(char *name, long ttl, int type, char *s) { - struct rr_px *rr = getmem(sizeof(*rr)); + struct rr_px *rr = getmem(sizeof(*rr)); - rr->preference = extract_integer(&s, "PX preference", NULL); - if (rr->preference < 0) - return NULL; + rr->preference = extract_integer(&s, "PX preference", NULL); + if (rr->preference < 0) + return NULL; - rr->map822 = extract_name(&s, "map822", 0); - if (!rr->map822) - return NULL; + rr->map822 = extract_name(&s, "map822", 0); + if (!rr->map822) + return NULL; - rr->mapx400 = extract_name(&s, "mapx400", 0); - if (!rr->mapx400) - return NULL; + rr->mapx400 = extract_name(&s, "mapx400", 0); + if (!rr->mapx400) + return NULL; - if (*s) { - return bitch("garbage after valid KX data"); - } + if (*s) { + return bitch("garbage after valid KX data"); + } - return store_record(type, name, ttl, rr); + return store_record(type, name, ttl, rr); } static char* px_human(struct rr *rrv) { - RRCAST(px); + RRCAST(px); char s[1024]; snprintf(s, 1024, "%d %s %s", - rr->preference, rr->map822, rr->mapx400); + rr->preference, rr->map822, rr->mapx400); return quickstrdup_temp(s); } static struct binary_data px_wirerdata(struct rr *rrv) { - RRCAST(px); + RRCAST(px); return compose_binary_data("2dd", 1, - rr->preference, - name2wire_name(rr->map822), - name2wire_name(rr->mapx400)); + rr->preference, + name2wire_name(rr->map822), + name2wire_name(rr->mapx400)); } struct rr_methods px_methods = { px_parse, px_human, px_wirerdata, NULL, NULL }; diff --git a/rp.c b/rp.c index 8b3cdc4..973ac39 100644 --- a/rp.c +++ b/rp.c @@ -20,26 +20,26 @@ static struct rr *rp_parse(char *name, long ttl, int type, char *s) { - struct rr_rp *rr = getmem(sizeof(*rr)); + struct rr_rp *rr = getmem(sizeof(*rr)); - rr->mbox_dname = extract_name(&s, "mbox domain name", 0); - if (!rr->mbox_dname) - return NULL; + rr->mbox_dname = extract_name(&s, "mbox domain name", 0); + if (!rr->mbox_dname) + return NULL; - rr->txt_dname = extract_name(&s, "txt domain name", 0); - if (!rr->txt_dname) - return NULL; + rr->txt_dname = extract_name(&s, "txt domain name", 0); + if (!rr->txt_dname) + return NULL; - if (*s) { - return bitch("garbage after valid RP data"); - } + if (*s) { + return bitch("garbage after valid RP data"); + } - return store_record(type, name, ttl, rr); + return store_record(type, name, ttl, rr); } static char* rp_human(struct rr *rrv) { - RRCAST(rp); + RRCAST(rp); char s[1024]; snprintf(s, 1024, "\"%s\" \"%s\"", rr->mbox_dname, rr->txt_dname); @@ -48,24 +48,24 @@ static char* rp_human(struct rr *rrv) static struct binary_data rp_wirerdata(struct rr *rrv) { - RRCAST(rp); + RRCAST(rp); - return compose_binary_data("dd", 1, - name2wire_name(rr->mbox_dname), - name2wire_name(rr->txt_dname)); + return compose_binary_data("dd", 1, + name2wire_name(rr->mbox_dname), + name2wire_name(rr->txt_dname)); } static void *rp_validate(struct rr *rrv) { - RRCAST(rp); + RRCAST(rp); - if (G.opt.policy_checks[POLICY_RP_TXT_EXISTS]) { - if (name_belongs_to_zone(rr->txt_dname) && !find_rr_set(T_TXT, rr->txt_dname)) { - return moan(rr->rr.file_name, rr->rr.line, "%s RP TXT %s does not exist", - rr->rr.rr_set->named_rr->name, rr->txt_dname); - } - } - return NULL; + if (G.opt.policy_checks[POLICY_RP_TXT_EXISTS]) { + if (name_belongs_to_zone(rr->txt_dname) && !find_rr_set(T_TXT, rr->txt_dname)) { + return moan(rr->rr.file_name, rr->rr.line, "%s RP TXT %s does not exist", + rr->rr.rr_set->named_rr->name, rr->txt_dname); + } + } + return NULL; } struct rr_methods rp_methods = { rp_parse, rp_human, rp_wirerdata, NULL, rp_validate }; diff --git a/rr.c b/rr.c index d204ffe..4006301 100644 --- a/rr.c +++ b/rr.c @@ -20,71 +20,71 @@ #include "cbtree.h" static char* rdtype2str_map[T_MAX+1] = { - "0", - "A", - "NS", - "MD", - "MF", - "CNAME", /* 5 */ - "SOA", - "MB", - "MG", - "MR", - "NULL", /* 10 */ - "WKS", - "PTR", - "HINFO", - "MINFO", - "MX", /* 15 */ - "TXT", - "RP", - "AFSDB", - "X25", - "ISDN", /* 20 */ - "RT", - "NSAP", - "NSAP-PTR", - "SIG", - "KEY", /* 25 */ - "PX", - "GPOS", - "AAAA", - "LOC", - "NXT", /* 30 */ - "EID", - "NIMLOC", - "SRV", - "ATMA", - "NAPTR", /* 35 */ - "KX", - "CERT", - "A6", - "DNAME", - "SINK", /* 40 */ - "OPT", - "APL", - "DS", - "SSHFP", - "IPSECKEY", /* 45 */ - "RRSIG", - "NSEC", - "DNSKEY", - "DHCID", - "NSEC3", /* 50 */ - "NSEC3PARAM", - "TLSA", - 0, 0, 0, 0, 0, 0, 0, 0, /* 60 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 70 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 */ - 0, 0, 0, 0, 0, 0, 0, 0, - "SPF", - 0, /* 100 */ - 0, 0, 0, - "NID", - "L32", - "L64", - "LP", + "0", + "A", + "NS", + "MD", + "MF", + "CNAME", /* 5 */ + "SOA", + "MB", + "MG", + "MR", + "NULL", /* 10 */ + "WKS", + "PTR", + "HINFO", + "MINFO", + "MX", /* 15 */ + "TXT", + "RP", + "AFSDB", + "X25", + "ISDN", /* 20 */ + "RT", + "NSAP", + "NSAP-PTR", + "SIG", + "KEY", /* 25 */ + "PX", + "GPOS", + "AAAA", + "LOC", + "NXT", /* 30 */ + "EID", + "NIMLOC", + "SRV", + "ATMA", + "NAPTR", /* 35 */ + "KX", + "CERT", + "A6", + "DNAME", + "SINK", /* 40 */ + "OPT", + "APL", + "DS", + "SSHFP", + "IPSECKEY", /* 45 */ + "RRSIG", + "NSEC", + "DNSKEY", + "DHCID", + "NSEC3", /* 50 */ + "NSEC3PARAM", + "TLSA", + 0, 0, 0, 0, 0, 0, 0, 0, /* 60 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 70 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 */ + 0, 0, 0, 0, 0, 0, 0, 0, + "SPF", + 0, /* 100 */ + 0, 0, 0, + "NID", + "L32", + "L64", + "LP", }; struct cbtree zone_data = {NULL}; char *zone_apex = NULL; @@ -92,795 +92,795 @@ int zone_apex_l = 0; char *rdtype2str(int type) { - char s[10]; - char *r; - if (type < 0 || type > 65535) { - return "???"; - } - if (type > T_MAX) { - sprintf(s, "TYPE%d", type); - return quickstrdup_temp(s); - } - r = rdtype2str_map[type]; - if (r) return r; - if (type == 32769) { - return rdtype2str_map[type] = "DLV"; - } - sprintf(s, "TYPE%d", type); - return quickstrdup_temp(s); + char s[10]; + char *r; + if (type < 0 || type > 65535) { + return "???"; + } + if (type > T_MAX) { + sprintf(s, "TYPE%d", type); + return quickstrdup_temp(s); + } + r = rdtype2str_map[type]; + if (r) return r; + if (type == 32769) { + return rdtype2str_map[type] = "DLV"; + } + sprintf(s, "TYPE%d", type); + return quickstrdup_temp(s); } static unsigned char *name2findable_name(char *s) { - int l = strlen(s); - unsigned char *res = getmem_temp(l+1); - unsigned char *r = res; - int i; - - if (l > 0 && s[l-1] == '.') - l--; - while (--l >= 0) { - i = l; - while (i >= 0 && s[i] != '.') - i--; - memcpy(r, s+i+1, l-i); - r += l-i; - *r = '\x01'; - r++; - l = i; - } - if (r > res) r--; - *r = 0; - return res; + int l = strlen(s); + unsigned char *res = getmem_temp(l+1); + unsigned char *r = res; + int i; + + if (l > 0 && s[l-1] == '.') + l--; + while (--l >= 0) { + i = l; + while (i >= 0 && s[i] != '.') + i--; + memcpy(r, s+i+1, l-i); + r += l-i; + *r = '\x01'; + r++; + l = i; + } + if (r > res) r--; + *r = 0; + return res; } struct binary_data name2wire_name(char *s) { - unsigned char *res = getmem_temp(strlen(s)+2); - unsigned char *r = res; - unsigned char *c = res; - struct binary_data toret; - - r++; - *c = 0; - while (*s) { - if (*s != '.') { - *r++ = *s++; - } else { - *c = (unsigned char)(r-c-1); - c = r; - *c = 0; - r++; - s++; - } - } - *c = (unsigned char)(r-c-1); - toret.length = r-res; - toret.data = (char*)res; - if (toret.length == 2) /* "." is just 00, not 00 00 */ - toret.length = 1; - return toret; + unsigned char *res = getmem_temp(strlen(s)+2); + unsigned char *r = res; + unsigned char *c = res; + struct binary_data toret; + + r++; + *c = 0; + while (*s) { + if (*s != '.') { + *r++ = *s++; + } else { + *c = (unsigned char)(r-c-1); + c = r; + *c = 0; + r++; + s++; + } + } + *c = (unsigned char)(r-c-1); + toret.length = r-res; + toret.data = (char*)res; + if (toret.length == 2) /* "." is just 00, not 00 00 */ + toret.length = 1; + return toret; } static struct named_rr *find_or_create_named_rr(char *name) { - struct named_rr *named_rr = find_named_rr(name); - - if (!named_rr) { - struct named_rr **named_rr_slot; - char *s; - - named_rr = getmem(sizeof(struct named_rr)); - named_rr->name = quickstrdup(name); - named_rr->rr_sets = NULL; - named_rr->line = file_info->line; - named_rr->file_name = file_info->name; - named_rr->flags = 0; - named_rr->parent = NULL; - - if (strchr(name, '/') != NULL) - named_rr->flags |= NAME_FLAG_CONTAINS_SLASH; - - named_rr_slot = (void *)cbtree_insert(&zone_data, (char *)name2findable_name(name)); - if (!named_rr_slot) - croak(2, "find_or_create_named_rr: tree insertion failed"); - if (*named_rr_slot) - croak(3, "find_or_create_named_rr: assertion error, %s should not be there", name); - *named_rr_slot = named_rr; - G.stats.names_count++; - - s = strchr(name, '.'); - if (s && s[1] != '\0') { - named_rr->parent = find_or_create_named_rr(s+1); - } - } - - return named_rr; + struct named_rr *named_rr = find_named_rr(name); + + if (!named_rr) { + struct named_rr **named_rr_slot; + char *s; + + named_rr = getmem(sizeof(struct named_rr)); + named_rr->name = quickstrdup(name); + named_rr->rr_sets = NULL; + named_rr->line = file_info->line; + named_rr->file_name = file_info->name; + named_rr->flags = 0; + named_rr->parent = NULL; + + if (strchr(name, '/') != NULL) + named_rr->flags |= NAME_FLAG_CONTAINS_SLASH; + + named_rr_slot = (void *)cbtree_insert(&zone_data, (char *)name2findable_name(name)); + if (!named_rr_slot) + croak(2, "find_or_create_named_rr: tree insertion failed"); + if (*named_rr_slot) + croak(3, "find_or_create_named_rr: assertion error, %s should not be there", name); + *named_rr_slot = named_rr; + G.stats.names_count++; + + s = strchr(name, '.'); + if (s && s[1] != '\0') { + named_rr->parent = find_or_create_named_rr(s+1); + } + } + + return named_rr; } static struct rr_set *find_or_create_rr_set(struct named_rr *named_rr, int rdtype) { - struct rr_set *rr_set = find_rr_set_in_named_rr(named_rr, rdtype); - if (!rr_set) { - struct rr_set **rr_set_slot; - - rr_set = getmem(sizeof(struct rr_set)); - rr_set->head = NULL; - rr_set->tail = NULL; - rr_set->named_rr = named_rr; - rr_set->rdtype = rdtype; - rr_set->count = 0; - - JLI(rr_set_slot, named_rr->rr_sets, rdtype); - if (rr_set_slot == PJERR) - croak(2, "find_or_create_rr_set: JLI failed"); - if (*rr_set_slot) - croak(3, "find_or_create_rr_set: assertion error, %s/%s should not be there", - named_rr->name, rdtype2str(rdtype)); - *rr_set_slot = rr_set; - G.stats.rrset_count++; - } - return rr_set; + struct rr_set *rr_set = find_rr_set_in_named_rr(named_rr, rdtype); + if (!rr_set) { + struct rr_set **rr_set_slot; + + rr_set = getmem(sizeof(struct rr_set)); + rr_set->head = NULL; + rr_set->tail = NULL; + rr_set->named_rr = named_rr; + rr_set->rdtype = rdtype; + rr_set->count = 0; + + JLI(rr_set_slot, named_rr->rr_sets, rdtype); + if (rr_set_slot == PJERR) + croak(2, "find_or_create_rr_set: JLI failed"); + if (*rr_set_slot) + croak(3, "find_or_create_rr_set: assertion error, %s/%s should not be there", + named_rr->name, rdtype2str(rdtype)); + *rr_set_slot = rr_set; + G.stats.rrset_count++; + } + return rr_set; } int name_belongs_to_zone(const char *name) { - int name_l; - - name_l = strlen(name); - if (zone_apex && name_l >= zone_apex_l) { - if (strcmp(zone_apex, name+name_l-zone_apex_l) != 0) { - return 0; - } else if (name_l > zone_apex_l && name[name_l-zone_apex_l-1] != '.') { - return 0; - } - } else { - if (zone_apex) { - return 0; - } else { - // XXX this is actually very bad, zone apex is not know - return 0; - } - } - return 1; + int name_l; + + name_l = strlen(name); + if (zone_apex && name_l >= zone_apex_l) { + if (strcmp(zone_apex, name+name_l-zone_apex_l) != 0) { + return 0; + } else if (name_l > zone_apex_l && name[name_l-zone_apex_l-1] != '.') { + return 0; + } + } else { + if (zone_apex) { + return 0; + } else { + // XXX this is actually very bad, zone apex is not know + return 0; + } + } + return 1; } struct binary_data call_get_wired(struct rr *rr) { - rr_wire_func get_wired; - - if (rr->rdtype > T_MAX || rr->is_generic) - get_wired = any_wirerdata; - else - get_wired = rr_methods[rr->rdtype].rr_wire; - if (!get_wired) return bad_binary_data(); - return get_wired(rr); + rr_wire_func get_wired; + + if (rr->rdtype > T_MAX || rr->is_generic) + get_wired = any_wirerdata; + else + get_wired = rr_methods[rr->rdtype].rr_wire; + if (!get_wired) return bad_binary_data(); + return get_wired(rr); } struct rr *store_record(int rdtype, char *name, long ttl, void *rrptr) { - struct rr *rr = rrptr; - struct named_rr *named_rr; - struct rr_set *rr_set; - int name_l; - int apex_assigned = 0; - int is_generic = 0; - - if (rdtype < 0) { - rdtype = -rdtype; - is_generic = 1; - } - name_l = strlen(name); - if (name_l > 511) - return bitch("name is too long: %s", name); - - if (G.stats.rr_count == 0) { - if (rdtype != T_SOA) { - return bitch("the first record in the zone must be an SOA record"); - } else { - zone_apex = name; - zone_apex_l = name_l; - apex_assigned = 1; - } - } - if (zone_apex && name_l >= zone_apex_l) { - if (strcmp(zone_apex, name+name_l-zone_apex_l) != 0) { - return bitch("%s does not belong to zone %s", name, zone_apex); - } else if (name_l > zone_apex_l && name[name_l-zone_apex_l-1] != '.') { - return bitch("%s does not belong to zone %s", name, zone_apex); - } - } else { - if (zone_apex) { - return bitch("%s does not belong to zone %s", name, zone_apex); - } else { - croakx(3, "assertion error: %s does not belong to a zone", name); - } - } - - named_rr = find_or_create_named_rr(name); - if (apex_assigned) { - named_rr->flags |= NAME_FLAG_APEX; - } - rr_set = find_or_create_rr_set(named_rr, rdtype); - - rr->rdtype = rdtype; - rr->ttl = ttl; - rr->line = file_info->line; - rr->file_name = file_info->name; - rr->is_generic = is_generic; - - if (rr_set->count > 0) { - struct binary_data new_d, old_d; - struct rr *old_rr; - - new_d = call_get_wired(rr); - if (new_d.length < 0) goto after_dup_check; - - old_rr = rr_set->tail; - while (old_rr) { - old_d = call_get_wired(old_rr); - if (old_d.length == new_d.length && - memcmp(old_d.data, new_d.data, old_d.length) == 0) - { - G.stats.skipped_dup_rr_count++; - return old_rr; - } - old_rr = old_rr->next; - } - } + struct rr *rr = rrptr; + struct named_rr *named_rr; + struct rr_set *rr_set; + int name_l; + int apex_assigned = 0; + int is_generic = 0; + + if (rdtype < 0) { + rdtype = -rdtype; + is_generic = 1; + } + name_l = strlen(name); + if (name_l > 511) + return bitch("name is too long: %s", name); + + if (G.stats.rr_count == 0) { + if (rdtype != T_SOA) { + return bitch("the first record in the zone must be an SOA record"); + } else { + zone_apex = name; + zone_apex_l = name_l; + apex_assigned = 1; + } + } + if (zone_apex && name_l >= zone_apex_l) { + if (strcmp(zone_apex, name+name_l-zone_apex_l) != 0) { + return bitch("%s does not belong to zone %s", name, zone_apex); + } else if (name_l > zone_apex_l && name[name_l-zone_apex_l-1] != '.') { + return bitch("%s does not belong to zone %s", name, zone_apex); + } + } else { + if (zone_apex) { + return bitch("%s does not belong to zone %s", name, zone_apex); + } else { + croakx(3, "assertion error: %s does not belong to a zone", name); + } + } + + named_rr = find_or_create_named_rr(name); + if (apex_assigned) { + named_rr->flags |= NAME_FLAG_APEX; + } + rr_set = find_or_create_rr_set(named_rr, rdtype); + + rr->rdtype = rdtype; + rr->ttl = ttl; + rr->line = file_info->line; + rr->file_name = file_info->name; + rr->is_generic = is_generic; + + if (rr_set->count > 0) { + struct binary_data new_d, old_d; + struct rr *old_rr; + + new_d = call_get_wired(rr); + if (new_d.length < 0) goto after_dup_check; + + old_rr = rr_set->tail; + while (old_rr) { + old_d = call_get_wired(old_rr); + if (old_d.length == new_d.length && + memcmp(old_d.data, new_d.data, old_d.length) == 0) + { + G.stats.skipped_dup_rr_count++; + return old_rr; + } + old_rr = old_rr->next; + } + } after_dup_check: - if (rdtype == T_SOA) { - if (G.stats.soa_rr_count++) { - return bitch("there could only be one SOA in a zone"); - } - } - - rr->rr_set = rr_set; - rr->next = NULL; - rr->prev = rr_set->head; - rr_set->head = rr; - if (rr->prev) - rr->prev->next = rr; - if (!rr_set->tail) - rr_set->tail = rr; - - rr_set->count++; - - if (G.opt.verbose) { - char *rdata; - if (rdtype > T_MAX) - rdata = any_human(rr); - else - rdata = rr_methods[rdtype].rr_human(rr); - fprintf(stderr, "-> %s:%d: %s IN %ld %s", - file_info->name, file_info->line, - name, ttl, rdtype2str(rdtype)); - if (rdata) { - fprintf(stderr, " %s\n", rdata); - } else { - fprintf(stderr, "\n"); - } - } - - G.stats.rr_count++; - named_rr->flags |= NAME_FLAG_HAS_RECORDS; - - return rr; + if (rdtype == T_SOA) { + if (G.stats.soa_rr_count++) { + return bitch("there could only be one SOA in a zone"); + } + } + + rr->rr_set = rr_set; + rr->next = NULL; + rr->prev = rr_set->head; + rr_set->head = rr; + if (rr->prev) + rr->prev->next = rr; + if (!rr_set->tail) + rr_set->tail = rr; + + rr_set->count++; + + if (G.opt.verbose) { + char *rdata; + if (rdtype > T_MAX) + rdata = any_human(rr); + else + rdata = rr_methods[rdtype].rr_human(rr); + fprintf(stderr, "-> %s:%d: %s IN %ld %s", + file_info->name, file_info->line, + name, ttl, rdtype2str(rdtype)); + if (rdata) { + fprintf(stderr, " %s\n", rdata); + } else { + fprintf(stderr, "\n"); + } + } + + G.stats.rr_count++; + named_rr->flags |= NAME_FLAG_HAS_RECORDS; + + return rr; } struct named_rr *find_named_rr(char *name) { - struct named_rr **named_rr_slot; + struct named_rr **named_rr_slot; - named_rr_slot = (void*) cbtree_find(&zone_data, (char *)name2findable_name(name)); - if (named_rr_slot) - return *named_rr_slot; - return NULL; + named_rr_slot = (void*) cbtree_find(&zone_data, (char *)name2findable_name(name)); + if (named_rr_slot) + return *named_rr_slot; + return NULL; } struct named_rr *find_next_named_rr(struct named_rr *named_rr) { - struct named_rr *res; + struct named_rr *res; - if (cbtree_next(&zone_data, (char *)name2findable_name(named_rr->name), (intptr_t *)&res) == NULL) - return NULL; + if (cbtree_next(&zone_data, (char *)name2findable_name(named_rr->name), (intptr_t *)&res) == NULL) + return NULL; - return res; + return res; } struct rr_set *find_rr_set(int rdtype, char *name) { - struct named_rr *named_rr; + struct named_rr *named_rr; - named_rr = find_named_rr(name); - if (!named_rr) - return NULL; + named_rr = find_named_rr(name); + if (!named_rr) + return NULL; - return find_rr_set_in_named_rr(named_rr, rdtype); + return find_rr_set_in_named_rr(named_rr, rdtype); } struct rr_set *find_rr_set_in_named_rr(struct named_rr *named_rr, int rdtype) { - struct rr_set **rr_set_slot; + struct rr_set **rr_set_slot; - JLG(rr_set_slot, named_rr->rr_sets, rdtype); - if (rr_set_slot) - return *rr_set_slot; - return NULL; + JLG(rr_set_slot, named_rr->rr_sets, rdtype); + if (rr_set_slot) + return *rr_set_slot; + return NULL; } uint32_t get_rr_set_count(struct named_rr *named_rr) { - uint32_t count; - JLC(count, named_rr->rr_sets, 0, -1); - return count; + uint32_t count; + JLC(count, named_rr->rr_sets, 0, -1); + return count; } struct rr *rr_parse_any(char *name, long ttl, int type, char *s) { - struct rr_any *rr = getmem(sizeof(*rr)); - long long len; + struct rr_any *rr = getmem(sizeof(*rr)); + long long len; - if (*s++ != '\\') { + if (*s++ != '\\') { invalid: - return bitch("invalid custom type rdata"); - } - if (*s++ != '#') - goto invalid; - if (*s && !isspace(*s) && *s != ';' && *s != ')') - goto invalid; - s = skip_white_space(s); - if (!s) return NULL; - - len = extract_integer(&s, "custom data size", NULL); - if (len < 0) return NULL; - if (len > 65535) goto invalid; - - rr->data = extract_hex_binary_data(&s, "custom data", EXTRACT_EAT_WHITESPACE); - if (rr->data.length < 0) return NULL; - if (rr->data.length != len) - return bitch("custom data is longer than specified"); - - if (*s) { - return bitch("garbage after valid %s data", rdtype2str(type)); - } - - return store_record(-type, name, ttl, rr); + return bitch("invalid custom type rdata"); + } + if (*s++ != '#') + goto invalid; + if (*s && !isspace(*s) && *s != ';' && *s != ')') + goto invalid; + s = skip_white_space(s); + if (!s) return NULL; + + len = extract_integer(&s, "custom data size", NULL); + if (len < 0) return NULL; + if (len > 65535) goto invalid; + + rr->data = extract_hex_binary_data(&s, "custom data", EXTRACT_EAT_WHITESPACE); + if (rr->data.length < 0) return NULL; + if (rr->data.length != len) + return bitch("custom data is longer than specified"); + + if (*s) { + return bitch("garbage after valid %s data", rdtype2str(type)); + } + + return store_record(-type, name, ttl, rr); } char* any_human(struct rr *rrv) { - RRCAST(any); - char buf[80]; + RRCAST(any); + char buf[80]; - sprintf(buf, "\\# %d ...", rr->data.length); - return quickstrdup_temp(buf); + sprintf(buf, "\\# %d ...", rr->data.length); + return quickstrdup_temp(buf); } struct binary_data any_wirerdata(struct rr *rrv) { - RRCAST(any); + RRCAST(any); - return compose_binary_data("d", 1, rr->data); + return compose_binary_data("d", 1, rr->data); } struct rr_methods unknown_methods = { NULL, any_human, any_wirerdata, NULL, NULL }; int str2rdtype(char *rdtype, int *is_generic) { - if (!rdtype) return -1; - if (is_generic) *is_generic = 0; - switch (*rdtype) { - case 'a': - if (strcmp(rdtype, "a") == 0) { - return T_A; - } else if (strcmp(rdtype, "aaaa") == 0) { - return T_AAAA; - } else if (strcmp(rdtype, "afsdb") == 0) { - return T_AFSDB; - } - break; - case 'c': - if (strcmp(rdtype, "cname") == 0) { - return T_CNAME; - } else if (strcmp(rdtype, "cert") == 0) { - return T_CERT; - } - break; - case 'd': - if (strcmp(rdtype, "ds") == 0) { - return T_DS; - } else if (strcmp(rdtype, "dnskey") == 0) { - return T_DNSKEY; - } else if (strcmp(rdtype, "dname") == 0) { - return T_DNAME; - } else if (strcmp(rdtype, "dlv") == 0) { - return T_DLV; - } else if (strcmp(rdtype, "dhcid") == 0) { - return T_DHCID; - } - break; - case 'h': - if (strcmp(rdtype, "hinfo") == 0) { - return T_HINFO; - } - break; - case 'i': - if (strcmp(rdtype, "ipseckey") == 0) { - return T_IPSECKEY; - } else if (strcmp(rdtype, "isdn") == 0) { - return T_ISDN; - } - break; - case 'k': - if (strcmp(rdtype, "kx") == 0) { - return T_KX; - } - break; - case 'l': - if (strcmp(rdtype, "loc") == 0) { - return T_LOC; - } else if (strcmp(rdtype, "l32") == 0) { - return T_L32; - } else if (strcmp(rdtype, "l64") == 0) { - return T_L64; - } else if (strcmp(rdtype, "lp") == 0) { - return T_LP; - } - break; - case 'm': - if (strcmp(rdtype, "mx") == 0) { - return T_MX; - } else if (strcmp(rdtype, "mb") == 0) { - return T_MB; - } else if (strcmp(rdtype, "mg") == 0) { - return T_MG; - } else if (strcmp(rdtype, "minfo") == 0) { - return T_MINFO; - } else if (strcmp(rdtype, "mr") == 0) { - return T_MR; - } - break; - case 'n': - if (strcmp(rdtype, "ns") == 0) { - return T_NS; - } else if (strcmp(rdtype, "naptr") == 0) { - return T_NAPTR; - } else if (strcmp(rdtype, "nsec") == 0) { - return T_NSEC; - } else if (strcmp(rdtype, "nsec3") == 0) { - return T_NSEC3; - } else if (strcmp(rdtype, "nid") == 0) { - return T_NID; - } else if (strcmp(rdtype, "nsec3param") == 0) { - return T_NSEC3PARAM; - } else if (strcmp(rdtype, "nsap") == 0) { - return T_NSAP; - } - break; - case 'p': - if (strcmp(rdtype, "ptr") == 0) { - return T_PTR; - } else if (strcmp(rdtype, "px") == 0) { - return T_PX; - } - break; - case 'r': - if (strcmp(rdtype, "rrsig") == 0) { - return T_RRSIG; - } else if (strcmp(rdtype, "rp") == 0) { - return T_RP; - } else if (strcmp(rdtype, "rt") == 0) { - return T_RT; - } - break; - case 's': - if (strcmp(rdtype, "soa") == 0) { - return T_SOA; - } else if (strcmp(rdtype, "srv") == 0) { - return T_SRV; - } else if (strcmp(rdtype, "spf") == 0) { - return T_SPF; - } else if (strcmp(rdtype, "sshfp") == 0) { - return T_SSHFP; - } - break; - case 't': - if (strcmp(rdtype, "txt") == 0) { - return T_TXT; - } else if (strcmp(rdtype, "tlsa") == 0) { - return T_TLSA; - } else if (strncmp(rdtype, "type", 4) == 0) { - long type = strtol(rdtype+4, NULL, 10); - if (is_generic) *is_generic = 1; - if (type <= 0 || type > 65535) - bitch("invalid rdtype %s", rdtype); - return type; - } - break; - case 'x': - if (strcmp(rdtype, "x25") == 0) { - return T_X25; - } - break; - } - bitch("invalid or unsupported rdtype %s", rdtype); - return -1; + if (!rdtype) return -1; + if (is_generic) *is_generic = 0; + switch (*rdtype) { + case 'a': + if (strcmp(rdtype, "a") == 0) { + return T_A; + } else if (strcmp(rdtype, "aaaa") == 0) { + return T_AAAA; + } else if (strcmp(rdtype, "afsdb") == 0) { + return T_AFSDB; + } + break; + case 'c': + if (strcmp(rdtype, "cname") == 0) { + return T_CNAME; + } else if (strcmp(rdtype, "cert") == 0) { + return T_CERT; + } + break; + case 'd': + if (strcmp(rdtype, "ds") == 0) { + return T_DS; + } else if (strcmp(rdtype, "dnskey") == 0) { + return T_DNSKEY; + } else if (strcmp(rdtype, "dname") == 0) { + return T_DNAME; + } else if (strcmp(rdtype, "dlv") == 0) { + return T_DLV; + } else if (strcmp(rdtype, "dhcid") == 0) { + return T_DHCID; + } + break; + case 'h': + if (strcmp(rdtype, "hinfo") == 0) { + return T_HINFO; + } + break; + case 'i': + if (strcmp(rdtype, "ipseckey") == 0) { + return T_IPSECKEY; + } else if (strcmp(rdtype, "isdn") == 0) { + return T_ISDN; + } + break; + case 'k': + if (strcmp(rdtype, "kx") == 0) { + return T_KX; + } + break; + case 'l': + if (strcmp(rdtype, "loc") == 0) { + return T_LOC; + } else if (strcmp(rdtype, "l32") == 0) { + return T_L32; + } else if (strcmp(rdtype, "l64") == 0) { + return T_L64; + } else if (strcmp(rdtype, "lp") == 0) { + return T_LP; + } + break; + case 'm': + if (strcmp(rdtype, "mx") == 0) { + return T_MX; + } else if (strcmp(rdtype, "mb") == 0) { + return T_MB; + } else if (strcmp(rdtype, "mg") == 0) { + return T_MG; + } else if (strcmp(rdtype, "minfo") == 0) { + return T_MINFO; + } else if (strcmp(rdtype, "mr") == 0) { + return T_MR; + } + break; + case 'n': + if (strcmp(rdtype, "ns") == 0) { + return T_NS; + } else if (strcmp(rdtype, "naptr") == 0) { + return T_NAPTR; + } else if (strcmp(rdtype, "nsec") == 0) { + return T_NSEC; + } else if (strcmp(rdtype, "nsec3") == 0) { + return T_NSEC3; + } else if (strcmp(rdtype, "nid") == 0) { + return T_NID; + } else if (strcmp(rdtype, "nsec3param") == 0) { + return T_NSEC3PARAM; + } else if (strcmp(rdtype, "nsap") == 0) { + return T_NSAP; + } + break; + case 'p': + if (strcmp(rdtype, "ptr") == 0) { + return T_PTR; + } else if (strcmp(rdtype, "px") == 0) { + return T_PX; + } + break; + case 'r': + if (strcmp(rdtype, "rrsig") == 0) { + return T_RRSIG; + } else if (strcmp(rdtype, "rp") == 0) { + return T_RP; + } else if (strcmp(rdtype, "rt") == 0) { + return T_RT; + } + break; + case 's': + if (strcmp(rdtype, "soa") == 0) { + return T_SOA; + } else if (strcmp(rdtype, "srv") == 0) { + return T_SRV; + } else if (strcmp(rdtype, "spf") == 0) { + return T_SPF; + } else if (strcmp(rdtype, "sshfp") == 0) { + return T_SSHFP; + } + break; + case 't': + if (strcmp(rdtype, "txt") == 0) { + return T_TXT; + } else if (strcmp(rdtype, "tlsa") == 0) { + return T_TLSA; + } else if (strncmp(rdtype, "type", 4) == 0) { + long type = strtol(rdtype+4, NULL, 10); + if (is_generic) *is_generic = 1; + if (type <= 0 || type > 65535) + bitch("invalid rdtype %s", rdtype); + return type; + } + break; + case 'x': + if (strcmp(rdtype, "x25") == 0) { + return T_X25; + } + break; + } + bitch("invalid or unsupported rdtype %s", rdtype); + return -1; } void validate_rrset(struct rr_set *rr_set) { - struct rr *rr; - int ttl; - - /* This can happen when rr_set was allocated but - * nothing was added to it due to an error. */ - if (rr_set->count == 0) return; - rr = rr_set->tail; - if (!rr) { - croakx(4, "assertion failed: %s %s is null, but count is %d", - rdtype2str(rr_set->rdtype), rr_set->named_rr->name, - rr_set->count); - } - if (rr_set->rdtype < T_MAX && rr_methods[rr_set->rdtype].rr_validate_set) - rr_methods[rr_set->rdtype].rr_validate_set(rr_set); - ttl = rr->ttl; - - while (rr) { - validate_record(rr); - if (ttl != rr->ttl) { - if (rr->rdtype != T_RRSIG) /* RRSIG is an exception */ - moan(rr->file_name, rr->line, "TTL values differ within an RR set"); - } - rr = rr->next; - } + struct rr *rr; + int ttl; + + /* This can happen when rr_set was allocated but + * nothing was added to it due to an error. */ + if (rr_set->count == 0) return; + rr = rr_set->tail; + if (!rr) { + croakx(4, "assertion failed: %s %s is null, but count is %d", + rdtype2str(rr_set->rdtype), rr_set->named_rr->name, + rr_set->count); + } + if (rr_set->rdtype < T_MAX && rr_methods[rr_set->rdtype].rr_validate_set) + rr_methods[rr_set->rdtype].rr_validate_set(rr_set); + ttl = rr->ttl; + + while (rr) { + validate_record(rr); + if (ttl != rr->ttl) { + if (rr->rdtype != T_RRSIG) /* RRSIG is an exception */ + moan(rr->file_name, rr->line, "TTL values differ within an RR set"); + } + rr = rr->next; + } } void debug(struct named_rr *named_rr, char *s) { - fprintf(stderr, "%s %s", s, named_rr->name); - if ((named_rr->flags & NAME_FLAG_APEX)) - fprintf(stderr, ", apex"); - if ((named_rr->flags & NAME_FLAG_HAS_RECORDS)) - fprintf(stderr, ", has records"); - if ((named_rr->flags & NAME_FLAG_DELEGATION)) - fprintf(stderr, ", delegation"); - if ((named_rr->flags & NAME_FLAG_NOT_AUTHORITATIVE)) - fprintf(stderr, ", not auth"); - if ((named_rr->flags & NAME_FLAG_NSEC3_ONLY)) - fprintf(stderr, ", nsec3 only"); - if ((named_rr->flags & NAME_FLAG_KIDS_WITH_RECORDS)) - fprintf(stderr, ", kid records"); - if ((named_rr->flags & NAME_FLAG_SIGNED_DELEGATION)) - fprintf(stderr, ", signed delegation"); - if ((named_rr->flags & NAME_FLAG_APEX_PARENT)) - fprintf(stderr, ", apex parent"); - fprintf(stderr, "\n"); + fprintf(stderr, "%s %s", s, named_rr->name); + if ((named_rr->flags & NAME_FLAG_APEX)) + fprintf(stderr, ", apex"); + if ((named_rr->flags & NAME_FLAG_HAS_RECORDS)) + fprintf(stderr, ", has records"); + if ((named_rr->flags & NAME_FLAG_DELEGATION)) + fprintf(stderr, ", delegation"); + if ((named_rr->flags & NAME_FLAG_NOT_AUTHORITATIVE)) + fprintf(stderr, ", not auth"); + if ((named_rr->flags & NAME_FLAG_NSEC3_ONLY)) + fprintf(stderr, ", nsec3 only"); + if ((named_rr->flags & NAME_FLAG_KIDS_WITH_RECORDS)) + fprintf(stderr, ", kid records"); + if ((named_rr->flags & NAME_FLAG_SIGNED_DELEGATION)) + fprintf(stderr, ", signed delegation"); + if ((named_rr->flags & NAME_FLAG_APEX_PARENT)) + fprintf(stderr, ", apex parent"); + fprintf(stderr, "\n"); } static int validate_named_rr(const char *name, intptr_t *data, void *p) { - struct named_rr *named_rr = *((struct named_rr **)data); - Word_t rdtype; - struct rr_set **rr_set_p; - int nsec3_present = 0; - int nsec3_only = 1; - static int seen_apex = 0; - - if ((named_rr->flags & NAME_FLAG_APEX)) - seen_apex = 1; - if (!seen_apex) - named_rr->flags |= NAME_FLAG_APEX_PARENT; - - if (named_rr->parent && (named_rr->parent->flags & (NAME_FLAG_DELEGATION|NAME_FLAG_NOT_AUTHORITATIVE)) != 0) { - named_rr->flags |= NAME_FLAG_NOT_AUTHORITATIVE; - if ((named_rr->flags & NAME_FLAG_HAS_RECORDS) != 0) { - G.stats.not_authoritative++; - } - } - - if (G.nsec3_opt_out_present && (named_rr->flags & NAME_FLAG_DELEGATION)) { - JLG(rr_set_p, named_rr->rr_sets, T_DS); - if (!rr_set_p) - named_rr->flags |= NAME_FLAG_NOT_AUTHORITATIVE; - } + struct named_rr *named_rr = *((struct named_rr **)data); + Word_t rdtype; + struct rr_set **rr_set_p; + int nsec3_present = 0; + int nsec3_only = 1; + static int seen_apex = 0; + + if ((named_rr->flags & NAME_FLAG_APEX)) + seen_apex = 1; + if (!seen_apex) + named_rr->flags |= NAME_FLAG_APEX_PARENT; + + if (named_rr->parent && (named_rr->parent->flags & (NAME_FLAG_DELEGATION|NAME_FLAG_NOT_AUTHORITATIVE)) != 0) { + named_rr->flags |= NAME_FLAG_NOT_AUTHORITATIVE; + if ((named_rr->flags & NAME_FLAG_HAS_RECORDS) != 0) { + G.stats.not_authoritative++; + } + } + + if (G.nsec3_opt_out_present && (named_rr->flags & NAME_FLAG_DELEGATION)) { + JLG(rr_set_p, named_rr->rr_sets, T_DS); + if (!rr_set_p) + named_rr->flags |= NAME_FLAG_NOT_AUTHORITATIVE; + } //debug(named_rr, ">>>>"); - rdtype = 0; - JLF(rr_set_p, named_rr->rr_sets, rdtype); - - while (rr_set_p) { - validate_rrset(*rr_set_p); - if (rdtype == T_NSEC3) - nsec3_present = 1; - else if (rdtype != T_RRSIG) - nsec3_only = 0; - if (rdtype != T_NSEC3 && rdtype != T_RRSIG && rdtype != T_NS) - named_rr->flags |= NAME_FLAG_THIS_WITH_RECORDS; - if ((named_rr->flags & NAME_FLAG_NOT_AUTHORITATIVE) == 0 && - rdtype != T_NS && rdtype != T_NSEC3 && rdtype != T_RRSIG) - { - struct named_rr *nrr = named_rr; - int skip_first = rdtype == T_NS; - - while (nrr && (nrr->flags & NAME_FLAG_KIDS_WITH_RECORDS) == 0) { - if ((nrr->flags & NAME_FLAG_APEX_PARENT) || strlen(nrr->name) < zone_apex_l) { - nrr->flags |= NAME_FLAG_APEX_PARENT; - break; - } - if (!skip_first) - nrr->flags |= NAME_FLAG_KIDS_WITH_RECORDS; - skip_first = 0; - nrr = nrr->parent; - } - } - if (rdtype == T_DS) { - struct named_rr *nrr = named_rr; - while (nrr && (nrr->flags & (NAME_FLAG_DELEGATION|NAME_FLAG_NOT_AUTHORITATIVE)) != 0) { - // nrr->flags &= ~(NAME_FLAG_DELEGATION|NAME_FLAG_NOT_AUTHORITATIVE); - nrr->flags |= NAME_FLAG_SIGNED_DELEGATION; - nrr = nrr->parent; - } - } - JLN(rr_set_p, named_rr->rr_sets, rdtype); - } - if (nsec3_present && nsec3_only) { - named_rr->flags |= NAME_FLAG_NSEC3_ONLY; - } - return 1; + rdtype = 0; + JLF(rr_set_p, named_rr->rr_sets, rdtype); + + while (rr_set_p) { + validate_rrset(*rr_set_p); + if (rdtype == T_NSEC3) + nsec3_present = 1; + else if (rdtype != T_RRSIG) + nsec3_only = 0; + if (rdtype != T_NSEC3 && rdtype != T_RRSIG && rdtype != T_NS) + named_rr->flags |= NAME_FLAG_THIS_WITH_RECORDS; + if ((named_rr->flags & NAME_FLAG_NOT_AUTHORITATIVE) == 0 && + rdtype != T_NS && rdtype != T_NSEC3 && rdtype != T_RRSIG) + { + struct named_rr *nrr = named_rr; + int skip_first = rdtype == T_NS; + + while (nrr && (nrr->flags & NAME_FLAG_KIDS_WITH_RECORDS) == 0) { + if ((nrr->flags & NAME_FLAG_APEX_PARENT) || strlen(nrr->name) < zone_apex_l) { + nrr->flags |= NAME_FLAG_APEX_PARENT; + break; + } + if (!skip_first) + nrr->flags |= NAME_FLAG_KIDS_WITH_RECORDS; + skip_first = 0; + nrr = nrr->parent; + } + } + if (rdtype == T_DS) { + struct named_rr *nrr = named_rr; + while (nrr && (nrr->flags & (NAME_FLAG_DELEGATION|NAME_FLAG_NOT_AUTHORITATIVE)) != 0) { + // nrr->flags &= ~(NAME_FLAG_DELEGATION|NAME_FLAG_NOT_AUTHORITATIVE); + nrr->flags |= NAME_FLAG_SIGNED_DELEGATION; + nrr = nrr->parent; + } + } + JLN(rr_set_p, named_rr->rr_sets, rdtype); + } + if (nsec3_present && nsec3_only) { + named_rr->flags |= NAME_FLAG_NSEC3_ONLY; + } + return 1; } static void* nsec_validate_pass2(struct rr *rrv) { - RRCAST(nsec); - struct named_rr *named_rr, *next_named_rr; - - named_rr = rr->rr.rr_set->named_rr; - next_named_rr = find_next_named_rr(named_rr); - /* Skip empty non-terminals and not authoritative records from consideration */ - while (next_named_rr) { - if ((next_named_rr->flags & NAME_FLAG_HAS_RECORDS) == 0) { - next_named_rr = find_next_named_rr(next_named_rr); - continue; - } - if (next_named_rr->parent && - (next_named_rr->parent->flags & (NAME_FLAG_DELEGATION|NAME_FLAG_NOT_AUTHORITATIVE)) != 0) - { - named_rr->flags |= NAME_FLAG_NOT_AUTHORITATIVE; - next_named_rr = find_next_named_rr(next_named_rr); - continue; - } - break; - } - - if (strcasecmp(rr->next_domain, zone_apex) == 0) { - if (next_named_rr) { - return moan(rr->rr.file_name, rr->rr.line, "NSEC says %s is the last name, but %s exists", - named_rr->name, next_named_rr->name); - } - } else { - if (!next_named_rr) { - return moan(rr->rr.file_name, rr->rr.line, "NSEC says %s comes after %s, but nothing does", - rr->next_domain, named_rr->name); - } else if (strcasecmp(rr->next_domain, next_named_rr->name) != 0) { - return moan(rr->rr.file_name, rr->rr.line, "NSEC says %s comes after %s, but %s does", - rr->next_domain, named_rr->name, next_named_rr->name); - } - } - - /* TODO: more checks */ - return rr; + RRCAST(nsec); + struct named_rr *named_rr, *next_named_rr; + + named_rr = rr->rr.rr_set->named_rr; + next_named_rr = find_next_named_rr(named_rr); + /* Skip empty non-terminals and not authoritative records from consideration */ + while (next_named_rr) { + if ((next_named_rr->flags & NAME_FLAG_HAS_RECORDS) == 0) { + next_named_rr = find_next_named_rr(next_named_rr); + continue; + } + if (next_named_rr->parent && + (next_named_rr->parent->flags & (NAME_FLAG_DELEGATION|NAME_FLAG_NOT_AUTHORITATIVE)) != 0) + { + named_rr->flags |= NAME_FLAG_NOT_AUTHORITATIVE; + next_named_rr = find_next_named_rr(next_named_rr); + continue; + } + break; + } + + if (strcasecmp(rr->next_domain, zone_apex) == 0) { + if (next_named_rr) { + return moan(rr->rr.file_name, rr->rr.line, "NSEC says %s is the last name, but %s exists", + named_rr->name, next_named_rr->name); + } + } else { + if (!next_named_rr) { + return moan(rr->rr.file_name, rr->rr.line, "NSEC says %s comes after %s, but nothing does", + rr->next_domain, named_rr->name); + } else if (strcasecmp(rr->next_domain, next_named_rr->name) != 0) { + return moan(rr->rr.file_name, rr->rr.line, "NSEC says %s comes after %s, but %s does", + rr->next_domain, named_rr->name, next_named_rr->name); + } + } + + /* TODO: more checks */ + return rr; } static int second_pass_one_name(const char *name, intptr_t *data, void *p) { - struct named_rr *named_rr = *((struct named_rr **)data); - struct rr_set **rr_set_p; - - freeall_temp(); - JLG(rr_set_p, named_rr->rr_sets, T_NSEC); - if (rr_set_p && (*rr_set_p)->tail) { - nsec_validate_pass2((*rr_set_p)->tail); - } - return 1; + struct named_rr *named_rr = *((struct named_rr **)data); + struct rr_set **rr_set_p; + + freeall_temp(); + JLG(rr_set_p, named_rr->rr_sets, T_NSEC); + if (rr_set_p && (*rr_set_p)->tail) { + nsec_validate_pass2((*rr_set_p)->tail); + } + return 1; } void validate_zone(void) { - cbtree_allprefixed(&zone_data, "", validate_named_rr, NULL); - cbtree_allprefixed(&zone_data, "", second_pass_one_name, NULL); + cbtree_allprefixed(&zone_data, "", validate_named_rr, NULL); + cbtree_allprefixed(&zone_data, "", second_pass_one_name, NULL); - if (G.dnssec_active && !G.nsec3_present) - validate_nsec_chain(); + if (G.dnssec_active && !G.nsec3_present) + validate_nsec_chain(); } void validate_record(struct rr *rr) { - freeall_temp(); - if (!rr->is_generic && rr->rdtype < T_MAX && rr_methods[rr->rdtype].rr_validate) - rr_methods[rr->rdtype].rr_validate(rr); + freeall_temp(); + if (!rr->is_generic && rr->rdtype < T_MAX && rr_methods[rr->rdtype].rr_validate) + rr_methods[rr->rdtype].rr_validate(rr); } int extract_algorithm(char **s, char *what) { - int alg; - char *str_alg; - - if (isdigit(**s)) { - alg = extract_integer(s, what, NULL); - if (algorithm_type(alg) == ALG_UNSUPPORTED) { - bitch("bad or unsupported algorithm %d", alg); - return ALG_UNSUPPORTED; - } - return alg; - } else { - str_alg = extract_label(s, what, "temporary"); - if (!str_alg) return ALG_UNSUPPORTED; - if (strcmp(str_alg, "dsa") == 0) - return ALG_DSA; - if (strcmp(str_alg, "rsasha1") == 0) - return ALG_RSASHA1; - if (strcmp(str_alg, "dsa-nsec3-sha1") == 0) - return ALG_DSA_NSEC3_SHA1; - if (strcmp(str_alg, "rsasha1-nsec3-sha1") == 0) - return ALG_RSASHA1_NSEC3_SHA1; - if (strcmp(str_alg, "rsasha256") == 0) - return ALG_RSASHA256; - if (strcmp(str_alg, "rsasha512") == 0) - return ALG_RSASHA512; - - if (strcmp(str_alg, "ecc-gost") == 0) - return ALG_ECCGOST; - if (strcmp(str_alg, "ecdsap256sha256") == 0) - return ALG_ECDSAP256SHA256; - if (strcmp(str_alg, "ecdsap384sha384") == 0) - return ALG_ECDSAP384SHA384; - if (strcmp(str_alg, "ed25519") == 0) - return ALG_ED25519; - if (strcmp(str_alg, "ed448") == 0) - return ALG_ED448; - - if (strcmp(str_alg, "privatedns") == 0) - return ALG_PRIVATEDNS; - if (strcmp(str_alg, "privateoid") == 0) - return ALG_PRIVATEOID; - bitch("bad or unsupported algorithm %s", str_alg); - return ALG_UNSUPPORTED; - } + int alg; + char *str_alg; + + if (isdigit(**s)) { + alg = extract_integer(s, what, NULL); + if (algorithm_type(alg) == ALG_UNSUPPORTED) { + bitch("bad or unsupported algorithm %d", alg); + return ALG_UNSUPPORTED; + } + return alg; + } else { + str_alg = extract_label(s, what, "temporary"); + if (!str_alg) return ALG_UNSUPPORTED; + if (strcmp(str_alg, "dsa") == 0) + return ALG_DSA; + if (strcmp(str_alg, "rsasha1") == 0) + return ALG_RSASHA1; + if (strcmp(str_alg, "dsa-nsec3-sha1") == 0) + return ALG_DSA_NSEC3_SHA1; + if (strcmp(str_alg, "rsasha1-nsec3-sha1") == 0) + return ALG_RSASHA1_NSEC3_SHA1; + if (strcmp(str_alg, "rsasha256") == 0) + return ALG_RSASHA256; + if (strcmp(str_alg, "rsasha512") == 0) + return ALG_RSASHA512; + + if (strcmp(str_alg, "ecc-gost") == 0) + return ALG_ECCGOST; + if (strcmp(str_alg, "ecdsap256sha256") == 0) + return ALG_ECDSAP256SHA256; + if (strcmp(str_alg, "ecdsap384sha384") == 0) + return ALG_ECDSAP384SHA384; + if (strcmp(str_alg, "ed25519") == 0) + return ALG_ED25519; + if (strcmp(str_alg, "ed448") == 0) + return ALG_ED448; + + if (strcmp(str_alg, "privatedns") == 0) + return ALG_PRIVATEDNS; + if (strcmp(str_alg, "privateoid") == 0) + return ALG_PRIVATEOID; + bitch("bad or unsupported algorithm %s", str_alg); + return ALG_UNSUPPORTED; + } } int algorithm_type(int alg) { - switch (alg) { - case ALG_DSA: - return ALG_DSA_FAMILY; - case ALG_RSASHA1: - return ALG_RSA_FAMILY; - case ALG_DSA_NSEC3_SHA1: - return ALG_DSA_FAMILY; - case ALG_RSASHA1_NSEC3_SHA1: - return ALG_RSA_FAMILY; - case ALG_RSASHA256: - return ALG_RSA_FAMILY; - case ALG_RSASHA512: - return ALG_RSA_FAMILY; + switch (alg) { + case ALG_DSA: + return ALG_DSA_FAMILY; + case ALG_RSASHA1: + return ALG_RSA_FAMILY; + case ALG_DSA_NSEC3_SHA1: + return ALG_DSA_FAMILY; + case ALG_RSASHA1_NSEC3_SHA1: + return ALG_RSA_FAMILY; + case ALG_RSASHA256: + return ALG_RSA_FAMILY; + case ALG_RSASHA512: + return ALG_RSA_FAMILY; case ALG_ECCGOST: return ALG_ECC_FAMILY; case ALG_ECDSAP256SHA256: return ALG_ECC_FAMILY; case ALG_ECDSAP384SHA384: return ALG_ECC_FAMILY; - case ALG_ED25519: - return ALG_ECC_FAMILY; - case ALG_ED448: - return ALG_ECC_FAMILY; - case ALG_PRIVATEDNS: - return ALG_PRIVATE_FAMILY; - case ALG_PRIVATEOID: - return ALG_PRIVATE_FAMILY; - } - return ALG_UNSUPPORTED; + case ALG_ED25519: + return ALG_ECC_FAMILY; + case ALG_ED448: + return ALG_ECC_FAMILY; + case ALG_PRIVATEDNS: + return ALG_PRIVATE_FAMILY; + case ALG_PRIVATEOID: + return ALG_PRIVATE_FAMILY; + } + return ALG_UNSUPPORTED; } diff --git a/rr.h b/rr.h index 6cf8715..3ef7cbd 100644 --- a/rr.h +++ b/rr.h @@ -9,50 +9,50 @@ #ifndef _RR_H #define _RR_H 1 -#define T_A 1 -#define T_NS 2 -#define T_CNAME 5 -#define T_SOA 6 -#define T_MB 7 -#define T_MG 8 -#define T_MR 9 -#define T_PTR 12 -#define T_HINFO 13 -#define T_MINFO 14 -#define T_MX 15 -#define T_TXT 16 -#define T_RP 17 -#define T_AFSDB 18 -#define T_X25 19 -#define T_ISDN 20 -#define T_RT 21 -#define T_NSAP 22 -#define T_PX 26 -#define T_AAAA 28 -#define T_LOC 29 -#define T_SRV 33 -#define T_NAPTR 35 -#define T_KX 36 -#define T_CERT 37 -#define T_DNAME 39 -#define T_DS 43 -#define T_SSHFP 44 -#define T_IPSECKEY 45 -#define T_RRSIG 46 -#define T_NSEC 47 -#define T_DNSKEY 48 -#define T_DHCID 49 -#define T_NSEC3 50 -#define T_NSEC3PARAM 51 -#define T_TLSA 52 -#define T_SPF 99 -#define T_NID 104 -#define T_L32 105 -#define T_L64 106 -#define T_LP 107 +#define T_A 1 +#define T_NS 2 +#define T_CNAME 5 +#define T_SOA 6 +#define T_MB 7 +#define T_MG 8 +#define T_MR 9 +#define T_PTR 12 +#define T_HINFO 13 +#define T_MINFO 14 +#define T_MX 15 +#define T_TXT 16 +#define T_RP 17 +#define T_AFSDB 18 +#define T_X25 19 +#define T_ISDN 20 +#define T_RT 21 +#define T_NSAP 22 +#define T_PX 26 +#define T_AAAA 28 +#define T_LOC 29 +#define T_SRV 33 +#define T_NAPTR 35 +#define T_KX 36 +#define T_CERT 37 +#define T_DNAME 39 +#define T_DS 43 +#define T_SSHFP 44 +#define T_IPSECKEY 45 +#define T_RRSIG 46 +#define T_NSEC 47 +#define T_DNSKEY 48 +#define T_DHCID 49 +#define T_NSEC3 50 +#define T_NSEC3PARAM 51 +#define T_TLSA 52 +#define T_SPF 99 +#define T_NID 104 +#define T_L32 105 +#define T_L64 106 +#define T_LP 107 #define T_CAA 257 #define T_DLV 32769 -#define T_MAX 32769 +#define T_MAX 32769 #define ALG_DSA 3 #define ALG_RSASHA1 5 @@ -91,11 +91,11 @@ typedef struct binary_data (*rr_wire_func)(struct rr*); typedef void* (*rr_validate_set_func)(struct rr_set*); typedef void* (*rr_validate_func)(struct rr*); struct rr_methods { - rr_parse_func rr_parse; - rr_human_func rr_human; - rr_wire_func rr_wire; - rr_validate_set_func rr_validate_set; - rr_validate_func rr_validate; + rr_parse_func rr_parse; + rr_human_func rr_human; + rr_wire_func rr_wire; + rr_validate_set_func rr_validate_set; + rr_validate_func rr_validate; }; extern struct rr_methods rr_methods[T_MAX+1]; extern struct rr_methods unknown_methods; @@ -133,58 +133,58 @@ int extract_algorithm(char **s, char *what); struct named_rr { - char *name; - void *rr_sets; + char *name; + void *rr_sets; - int line; - char *file_name; - uint32_t flags; - struct named_rr *parent; + int line; + char *file_name; + uint32_t flags; + struct named_rr *parent; }; struct rr_set { - struct rr* head; - struct rr* tail; - struct named_rr *named_rr; - int rdtype; - int count; + struct rr* head; + struct rr* tail; + struct named_rr *named_rr; + int rdtype; + int count; }; struct rr { - struct rr* next; - struct rr* prev; - struct rr_set *rr_set; + struct rr* next; + struct rr* prev; + struct rr_set *rr_set; - int ttl; - int rdtype; + int ttl; + int rdtype; - int line; - int is_generic; - char *file_name; + int line; + int is_generic; + char *file_name; }; struct rr_any { - struct rr rr; - struct binary_data data; + struct rr rr; + struct binary_data data; }; struct rr_a { - struct rr rr; - struct in_addr address; + struct rr rr; + struct in_addr address; }; extern struct rr_methods a_methods; struct rr_soa { - struct rr rr; - uint32_t serial; - int refresh, retry, expire, minimum; - char *rname; - char *mname; + struct rr rr; + uint32_t serial; + int refresh, retry, expire, minimum; + char *rname; + char *mname; }; extern struct rr_methods soa_methods; @@ -200,19 +200,19 @@ struct rr_dhcid struct rr rr; int id_type; int digest_type; - struct binary_data digest; + struct binary_data digest; }; extern struct rr_methods dhcid_methods; struct rr_txt_segment { - struct binary_data txt; - struct rr_txt_segment *next; + struct binary_data txt; + struct rr_txt_segment *next; }; struct rr_txt { struct rr rr; int count; - struct rr_txt_segment *txt; + struct rr_txt_segment *txt; }; extern struct rr_methods txt_methods; @@ -229,16 +229,16 @@ extern struct rr_methods tlsa_methods; struct rr_ipseckey { struct rr rr; - uint8_t precedence; - uint8_t gateway_type; - uint8_t algorithm; - union { - char *gateway_none; /* gateway_type == 0 */ - struct in_addr gateway_ipv4; /* gateway_type == 1 */ - struct in6_addr gateway_ipv6; /* gateway_type == 2 */ - char *gateway_name; /* gateway_type == 3 */ - } gateway; - struct binary_data public_key; + uint8_t precedence; + uint8_t gateway_type; + uint8_t algorithm; + union { + char *gateway_none; /* gateway_type == 0 */ + struct in_addr gateway_ipv4; /* gateway_type == 1 */ + struct in6_addr gateway_ipv6; /* gateway_type == 2 */ + char *gateway_name; /* gateway_type == 3 */ + } gateway; + struct binary_data public_key; }; extern struct rr_methods ipseckey_methods; @@ -277,20 +277,20 @@ extern struct rr_methods lp_methods; struct rr_naptr { struct rr rr; - uint16_t order; - uint16_t preference; - struct binary_data flags; - struct binary_data services; - struct binary_data regexp; - char *replacement; + uint16_t order; + uint16_t preference; + struct binary_data flags; + struct binary_data services; + struct binary_data regexp; + char *replacement; }; extern struct rr_methods naptr_methods; struct rr_nsec { - struct rr rr; - char *next_domain; - struct binary_data type_bitmap; + struct rr rr; + char *next_domain; + struct binary_data type_bitmap; }; extern struct rr_methods nsec_methods; @@ -298,176 +298,176 @@ void validate_nsec_chain(void); struct rr_nsec3 { - struct rr rr; - uint8_t hash_algorithm; - uint8_t flags; - uint16_t iterations; - struct binary_data salt; - struct binary_data next_hashed_owner; - struct binary_data type_bitmap; - struct binary_data this_hashed_name; - struct named_rr *corresponding_name; - struct rr_nsec3 *next_nsec3; + struct rr rr; + uint8_t hash_algorithm; + uint8_t flags; + uint16_t iterations; + struct binary_data salt; + struct binary_data next_hashed_owner; + struct binary_data type_bitmap; + struct binary_data this_hashed_name; + struct named_rr *corresponding_name; + struct rr_nsec3 *next_nsec3; }; extern struct rr_methods nsec3_methods; struct rr_nsec3param { - struct rr rr; - uint8_t hash_algorithm; - uint8_t flags; - uint16_t iterations; - struct binary_data salt; + struct rr rr; + uint8_t hash_algorithm; + uint8_t flags; + uint16_t iterations; + struct binary_data salt; }; extern struct rr_methods nsec3param_methods; extern struct rr *nsec3param; struct rr_rrsig { - struct rr rr; - uint16_t type_covered; - int algorithm; - int labels; - int orig_ttl; - uint32_t sig_expiration; - uint32_t sig_inception; - uint16_t key_tag; - char *signer; - struct binary_data signature; + struct rr rr; + uint16_t type_covered; + int algorithm; + int labels; + int orig_ttl; + uint32_t sig_expiration; + uint32_t sig_inception; + uint16_t key_tag; + char *signer; + struct binary_data signature; }; extern struct rr_methods rrsig_methods; struct rr_srv { - struct rr rr; - uint16_t priority; - uint16_t weight; - uint16_t port; - char *target; + struct rr rr; + uint16_t priority; + uint16_t weight; + uint16_t port; + char *target; }; extern struct rr_methods srv_methods; struct rr_cname { - struct rr rr; - char *cname; + struct rr rr; + char *cname; }; extern struct rr_methods cname_methods; struct rr_mb { - struct rr rr; - char *madname; + struct rr rr; + char *madname; }; extern struct rr_methods mb_methods; struct rr_mg { - struct rr rr; - char *mgmname; + struct rr rr; + char *mgmname; }; extern struct rr_methods mg_methods; struct rr_minfo { - struct rr rr; - char *rmailbx; - char *emailbx; + struct rr rr; + char *rmailbx; + char *emailbx; }; extern struct rr_methods minfo_methods; struct rr_mr { - struct rr rr; - char *newname; + struct rr rr; + char *newname; }; extern struct rr_methods mr_methods; struct rr_dname { - struct rr rr; - char *target; + struct rr rr; + char *target; }; extern struct rr_methods dname_methods; struct rr_aaaa { - struct rr rr; - struct in6_addr address; + struct rr rr; + struct in6_addr address; }; extern struct rr_methods aaaa_methods; struct rr_mx { - struct rr rr; - int preference; - char *exchange; + struct rr rr; + int preference; + char *exchange; }; extern struct rr_methods mx_methods; struct rr_rt { - struct rr rr; - int preference; - char *intermediate_host; + struct rr rr; + int preference; + char *intermediate_host; }; extern struct rr_methods rt_methods; struct rr_afsdb { - struct rr rr; - int subtype; - char *hostname; + struct rr rr; + int subtype; + char *hostname; }; extern struct rr_methods afsdb_methods; struct rr_x25 { - struct rr rr; + struct rr rr; struct binary_data psdn_address; }; extern struct rr_methods x25_methods; struct rr_isdn { - struct rr rr; + struct rr rr; struct binary_data isdn_address; struct binary_data sa; - int sa_present; + int sa_present; }; extern struct rr_methods isdn_methods; struct rr_px { - struct rr rr; - int preference; - char *map822; - char *mapx400; + struct rr rr; + int preference; + char *map822; + char *mapx400; }; extern struct rr_methods px_methods; struct rr_kx { - struct rr rr; - int preference; - char *exchanger; + struct rr rr; + int preference; + char *exchanger; }; extern struct rr_methods kx_methods; struct rr_dnskey { - struct rr rr; - uint16_t flags; - uint8_t protocol; - uint8_t algorithm; - struct binary_data pubkey; - /* calculated */ - uint16_t key_tag; - int pkey_built; - void *pkey; - /* extras */ - int key_type; - struct rr_dnskey *next_key; + struct rr rr; + uint16_t flags; + uint8_t protocol; + uint8_t algorithm; + struct binary_data pubkey; + /* calculated */ + uint16_t key_tag; + int pkey_built; + void *pkey; + /* extras */ + int key_type; + struct rr_dnskey *next_key; }; extern struct rr_methods dnskey_methods; @@ -480,34 +480,34 @@ void dnskey_ksk_policy_check(void); struct rr_ds { - struct rr rr; - uint16_t key_tag; - uint8_t algorithm; - uint8_t digest_type; - struct binary_data digest; + struct rr rr; + uint16_t key_tag; + uint8_t algorithm; + uint8_t digest_type; + struct binary_data digest; }; extern struct rr_methods ds_methods; struct rr_dlv { - struct rr rr; - uint16_t key_tag; - uint8_t algorithm; - uint8_t digest_type; - struct binary_data digest; + struct rr rr; + uint16_t key_tag; + uint8_t algorithm; + uint8_t digest_type; + struct binary_data digest; }; extern struct rr_methods dlv_methods; struct rr_nsap { - struct rr rr; - struct binary_data data; + struct rr rr; + struct binary_data data; }; extern struct rr_methods nsap_methods; struct rr_hinfo { - struct rr rr; + struct rr rr; struct binary_data cpu; struct binary_data os; }; @@ -515,7 +515,7 @@ extern struct rr_methods hinfo_methods; struct rr_rp { - struct rr rr; + struct rr rr; char *mbox_dname; char *txt_dname; }; @@ -523,14 +523,14 @@ extern struct rr_methods rp_methods; struct rr_loc { - struct rr rr; - uint8_t version; - uint8_t size; - uint8_t horiz_pre; - uint8_t vert_pre; - uint32_t latitude; - uint32_t longitude; - uint32_t altitude; + struct rr rr; + uint8_t version; + uint8_t size; + uint8_t horiz_pre; + uint8_t vert_pre; + uint32_t latitude; + uint32_t longitude; + uint32_t altitude; }; extern struct rr_methods loc_methods; @@ -545,15 +545,15 @@ struct rr_sshfp { struct rr rr; uint8_t algorithm; - uint8_t fp_type; - struct binary_data fingerprint; + uint8_t fp_type; + struct binary_data fingerprint; }; extern struct rr_methods sshfp_methods; struct rr_spf { struct rr rr; - int count; + int count; struct binary_data spf[1]; }; extern struct rr_methods spf_methods; @@ -561,10 +561,10 @@ extern struct rr_methods spf_methods; struct rr_cert { struct rr rr; - uint16_t type; - uint16_t key_tag; - int algorithm; - struct binary_data certificate; + uint16_t type; + uint16_t key_tag; + int algorithm; + struct binary_data certificate; }; extern struct rr_methods cert_methods; diff --git a/rrsig.c b/rrsig.c index d932939..e363516 100644 --- a/rrsig.c +++ b/rrsig.c @@ -26,151 +26,151 @@ struct verification_data { - struct verification_data *next; - EVP_MD_CTX ctx; - struct rr_dnskey *key; - struct rr_rrsig *rr; - int ok; - unsigned long openssl_error; + struct verification_data *next; + EVP_MD_CTX ctx; + struct rr_dnskey *key; + struct rr_rrsig *rr; + int ok; + unsigned long openssl_error; }; struct keys_to_verify { - struct keys_to_verify *next; - struct rr_rrsig *rr; - struct rr_set *signed_set; - int n_keys; - struct verification_data to_verify[1]; + struct keys_to_verify *next; + struct rr_rrsig *rr; + struct rr_set *signed_set; + int n_keys; + struct verification_data to_verify[1]; }; static struct keys_to_verify *all_keys_to_verify = NULL; static struct rr* rrsig_parse(char *name, long ttl, int type, char *s) { - struct rr_rrsig *rr = getmem(sizeof(*rr)); - int type_covered, key_tag; - char *str_type_covered; - struct binary_data sig; - long long ts; - - str_type_covered = extract_label(&s, "type covered", "temporary"); - if (!str_type_covered) return NULL; - type_covered = str2rdtype(str_type_covered, NULL); - if (type_covered <= 0 || type_covered > 65535) return NULL; - rr->type_covered = type_covered; - - rr->algorithm = extract_algorithm(&s, "algorithm"); - if (rr->algorithm == ALG_UNSUPPORTED) return NULL; - if (rr->algorithm == ALG_PRIVATEDNS || rr->algorithm == ALG_PRIVATEOID) { - return bitch("private algorithms are not supported in RRSIG"); - } - - rr->labels = extract_integer(&s, "labels", NULL); - if (rr->labels < 0) return NULL; - /* TODO validate labels, see http://tools.ietf.org/html/rfc4034#section-3.1.3 */ - - rr->orig_ttl = extract_timevalue(&s, "original TTL"); - if (rr->orig_ttl < 0) return NULL; - - ts = extract_timestamp(&s, "signature expiration"); - if (ts < 0) return NULL; - rr->sig_expiration = ts; - - ts = extract_timestamp(&s, "signature inception"); - if (ts < 0) return NULL; - rr->sig_inception = ts; - - key_tag = extract_integer(&s, "key tag", NULL); - if (key_tag < 0) return NULL; - rr->key_tag = key_tag; - - rr->signer = extract_name(&s, "signer name", 0); - if (!rr->signer) return NULL; - /* TODO validate signer name, http://tools.ietf.org/html/rfc4034#section-3.1.7 */ - - sig = extract_base64_binary_data(&s, "signature"); - if (sig.length < 0) return NULL; - /* TODO validate signature length based on algorithm */ - if (algorithm_type(rr->algorithm) == ALG_ECC_FAMILY) { - /* - * Transform ECDSA signatures from DNSSEC vanilla binary - * representation (r || s) into OpenSSL ASN.1 DER format - */ - ECDSA_SIG *ecdsa_sig = ECDSA_SIG_new(); - int l = sig.length / 2; - if ((BN_bin2bn((unsigned char *)sig.data, l, ecdsa_sig->r) == NULL) || - (BN_bin2bn(((unsigned char *)sig.data) + l, l, ecdsa_sig->s) == NULL)) - return NULL; - sig.length = i2d_ECDSA_SIG(ecdsa_sig, NULL); - sig.data = getmem(sig.length); /* reallocate larger mempool chunk */ - unsigned char *sig_ptr = (unsigned char *)sig.data; - sig.length = i2d_ECDSA_SIG(ecdsa_sig, &sig_ptr); - ECDSA_SIG_free(ecdsa_sig); - } - rr->signature = sig; - - if (*s) { - return bitch("garbage after valid RRSIG data"); - } - G.dnssec_active = 1; - return store_record(type, name, ttl, rr); + struct rr_rrsig *rr = getmem(sizeof(*rr)); + int type_covered, key_tag; + char *str_type_covered; + struct binary_data sig; + long long ts; + + str_type_covered = extract_label(&s, "type covered", "temporary"); + if (!str_type_covered) return NULL; + type_covered = str2rdtype(str_type_covered, NULL); + if (type_covered <= 0 || type_covered > 65535) return NULL; + rr->type_covered = type_covered; + + rr->algorithm = extract_algorithm(&s, "algorithm"); + if (rr->algorithm == ALG_UNSUPPORTED) return NULL; + if (rr->algorithm == ALG_PRIVATEDNS || rr->algorithm == ALG_PRIVATEOID) { + return bitch("private algorithms are not supported in RRSIG"); + } + + rr->labels = extract_integer(&s, "labels", NULL); + if (rr->labels < 0) return NULL; + /* TODO validate labels, see http://tools.ietf.org/html/rfc4034#section-3.1.3 */ + + rr->orig_ttl = extract_timevalue(&s, "original TTL"); + if (rr->orig_ttl < 0) return NULL; + + ts = extract_timestamp(&s, "signature expiration"); + if (ts < 0) return NULL; + rr->sig_expiration = ts; + + ts = extract_timestamp(&s, "signature inception"); + if (ts < 0) return NULL; + rr->sig_inception = ts; + + key_tag = extract_integer(&s, "key tag", NULL); + if (key_tag < 0) return NULL; + rr->key_tag = key_tag; + + rr->signer = extract_name(&s, "signer name", 0); + if (!rr->signer) return NULL; + /* TODO validate signer name, http://tools.ietf.org/html/rfc4034#section-3.1.7 */ + + sig = extract_base64_binary_data(&s, "signature"); + if (sig.length < 0) return NULL; + /* TODO validate signature length based on algorithm */ + if (algorithm_type(rr->algorithm) == ALG_ECC_FAMILY) { + /* + * Transform ECDSA signatures from DNSSEC vanilla binary + * representation (r || s) into OpenSSL ASN.1 DER format + */ + ECDSA_SIG *ecdsa_sig = ECDSA_SIG_new(); + int l = sig.length / 2; + if ((BN_bin2bn((unsigned char *)sig.data, l, ecdsa_sig->r) == NULL) || + (BN_bin2bn(((unsigned char *)sig.data) + l, l, ecdsa_sig->s) == NULL)) + return NULL; + sig.length = i2d_ECDSA_SIG(ecdsa_sig, NULL); + sig.data = getmem(sig.length); /* reallocate larger mempool chunk */ + unsigned char *sig_ptr = (unsigned char *)sig.data; + sig.length = i2d_ECDSA_SIG(ecdsa_sig, &sig_ptr); + ECDSA_SIG_free(ecdsa_sig); + } + rr->signature = sig; + + if (*s) { + return bitch("garbage after valid RRSIG data"); + } + G.dnssec_active = 1; + return store_record(type, name, ttl, rr); } static char* rrsig_human(struct rr *rrv) { - // RRCAST(rrsig); + // RRCAST(rrsig); // char s[1024]; //snprintf(s, 1024, "SOA %s %s %d %d %d %d %d", - // rr->mname, rr->rname, rr->serial, - // rr->refresh, rr->retry, rr->expire, rr->minimum); + // rr->mname, rr->rname, rr->serial, + // rr->refresh, rr->retry, rr->expire, rr->minimum); //return quickstrdup_temp(s); - return NULL; + return NULL; } static struct binary_data rrsig_wirerdata_ex(struct rr *rrv, int with_signature) { - RRCAST(rrsig); - struct binary_data bd; - - bd = compose_binary_data("2114442d", 1, - rr->type_covered, rr->algorithm, rr->labels, - rr->orig_ttl, rr->sig_expiration, rr->sig_inception, - rr->key_tag, name2wire_name(rr->signer)); - if (with_signature) { - return compose_binary_data("dd", 1, bd, rr->signature); - } - return bd; + RRCAST(rrsig); + struct binary_data bd; + + bd = compose_binary_data("2114442d", 1, + rr->type_covered, rr->algorithm, rr->labels, + rr->orig_ttl, rr->sig_expiration, rr->sig_inception, + rr->key_tag, name2wire_name(rr->signer)); + if (with_signature) { + return compose_binary_data("dd", 1, bd, rr->signature); + } + return bd; } static struct binary_data rrsig_wirerdata(struct rr *rrv) { - return rrsig_wirerdata_ex(rrv, 1); + return rrsig_wirerdata_ex(rrv, 1); } struct rr_with_wired { - struct rr *rr; - struct binary_data wired; + struct rr *rr; + struct binary_data wired; }; static int compare_rr_with_wired(const void *va, const void *vb) { - const struct rr_with_wired *a = va; - const struct rr_with_wired *b = vb; - int r; - - if (a->wired.length == b->wired.length) { - return memcmp(a->wired.data, b->wired.data, a->wired.length); - } else if (a->wired.length < b->wired.length) { - r = memcmp(a->wired.data, b->wired.data, a->wired.length); - if (r != 0) return r; - return -1; - } else { - r = memcmp(a->wired.data, b->wired.data, b->wired.length); - if (r != 0) return r; - return 1; - } + const struct rr_with_wired *a = va; + const struct rr_with_wired *b = vb; + int r; + + if (a->wired.length == b->wired.length) { + return memcmp(a->wired.data, b->wired.data, a->wired.length); + } else if (a->wired.length < b->wired.length) { + r = memcmp(a->wired.data, b->wired.data, a->wired.length); + if (r != 0) return r; + return -1; + } else { + r = memcmp(a->wired.data, b->wired.data, b->wired.length); + if (r != 0) return r; + return 1; + } } static struct verification_data *verification_queue = NULL; @@ -181,219 +181,219 @@ static pthread_t *workers; void *verification_thread(void *dummy) { - struct verification_data *d; - struct timespec sleep_time; - - while (1) { - if (pthread_mutex_lock(&queue_lock) != 0) - croak(1, "pthread_mutex_lock"); - d = verification_queue; - if (d) { - verification_queue = d->next; - G.stats.signatures_verified++; - } - if (pthread_mutex_unlock(&queue_lock) != 0) - croak(1, "pthread_mutex_unlock"); - if (d) { - int r; - d->next = NULL; - r = EVP_VerifyFinal(&d->ctx, (unsigned char *)d->rr->signature.data, d->rr->signature.length, d->key->pkey); - if (r == 1) { - d->ok = 1; - } else { - d->openssl_error = ERR_peek_last_error(); - } - if (pthread_mutex_lock(&queue_lock) != 0) - croak(1, "pthread_mutex_lock"); - verification_queue_size--; - if (pthread_mutex_unlock(&queue_lock) != 0) - croak(1, "pthread_mutex_unlock"); - } else { - sleep_time.tv_sec = 0; - sleep_time.tv_nsec = 10000000; - nanosleep(&sleep_time, NULL); - } - } + struct verification_data *d; + struct timespec sleep_time; + + while (1) { + if (pthread_mutex_lock(&queue_lock) != 0) + croak(1, "pthread_mutex_lock"); + d = verification_queue; + if (d) { + verification_queue = d->next; + G.stats.signatures_verified++; + } + if (pthread_mutex_unlock(&queue_lock) != 0) + croak(1, "pthread_mutex_unlock"); + if (d) { + int r; + d->next = NULL; + r = EVP_VerifyFinal(&d->ctx, (unsigned char *)d->rr->signature.data, d->rr->signature.length, d->key->pkey); + if (r == 1) { + d->ok = 1; + } else { + d->openssl_error = ERR_peek_last_error(); + } + if (pthread_mutex_lock(&queue_lock) != 0) + croak(1, "pthread_mutex_lock"); + verification_queue_size--; + if (pthread_mutex_unlock(&queue_lock) != 0) + croak(1, "pthread_mutex_unlock"); + } else { + sleep_time.tv_sec = 0; + sleep_time.tv_nsec = 10000000; + nanosleep(&sleep_time, NULL); + } + } } static void start_workers(void) { - int i; - - if (workers_started) - return; - if (G.opt.verbose) - fprintf(stderr, "starting workers for signature verification\n"); - workers = getmem(sizeof(*workers)*G.opt.n_threads); - for (i = 0; i < G.opt.n_threads; i++) { - if (pthread_create(&workers[i], NULL, verification_thread, NULL) != 0) - croak(1, "pthread_create"); - } - workers_started = 1; + int i; + + if (workers_started) + return; + if (G.opt.verbose) + fprintf(stderr, "starting workers for signature verification\n"); + workers = getmem(sizeof(*workers)*G.opt.n_threads); + for (i = 0; i < G.opt.n_threads; i++) { + if (pthread_create(&workers[i], NULL, verification_thread, NULL) != 0) + croak(1, "pthread_create"); + } + workers_started = 1; } static void schedule_verification(struct verification_data *d) { - int cur_size; - if (G.opt.n_threads > 1) { - if (pthread_mutex_lock(&queue_lock) != 0) - croak(1, "pthread_mutex_lock"); - d->next = verification_queue; - verification_queue = d; - verification_queue_size++; - cur_size = verification_queue_size; - if (pthread_mutex_unlock(&queue_lock) != 0) - croak(1, "pthread_mutex_unlock"); - if (!workers_started && cur_size >= G.opt.n_threads) - start_workers(); - } else { - int r; - G.stats.signatures_verified++; - r = EVP_VerifyFinal(&d->ctx, (unsigned char *)d->rr->signature.data, d->rr->signature.length, d->key->pkey); - if (r == 1) { - d->ok = 1; - } else { - d->openssl_error = ERR_peek_last_error(); - } - } + int cur_size; + if (G.opt.n_threads > 1) { + if (pthread_mutex_lock(&queue_lock) != 0) + croak(1, "pthread_mutex_lock"); + d->next = verification_queue; + verification_queue = d; + verification_queue_size++; + cur_size = verification_queue_size; + if (pthread_mutex_unlock(&queue_lock) != 0) + croak(1, "pthread_mutex_unlock"); + if (!workers_started && cur_size >= G.opt.n_threads) + start_workers(); + } else { + int r; + G.stats.signatures_verified++; + r = EVP_VerifyFinal(&d->ctx, (unsigned char *)d->rr->signature.data, d->rr->signature.length, d->key->pkey); + if (r == 1) { + d->ok = 1; + } else { + d->openssl_error = ERR_peek_last_error(); + } + } } static int verify_signature(struct verification_data *d, struct rr_set *signed_set) { - uint16_t b2; - uint32_t b4; - struct binary_data chunk; - struct rr_with_wired *set; - struct rr *signed_rr; - int i; - - EVP_MD_CTX_init(&d->ctx); - switch (d->rr->algorithm) { - case ALG_DSA: - case ALG_RSASHA1: - case ALG_DSA_NSEC3_SHA1: - case ALG_RSASHA1_NSEC3_SHA1: - if (EVP_VerifyInit(&d->ctx, EVP_sha1()) != 1) - return 0; - break; - case ALG_RSASHA256: - if (EVP_VerifyInit(&d->ctx, EVP_sha256()) != 1) - return 0; - break; - case ALG_RSASHA512: - if (EVP_VerifyInit(&d->ctx, EVP_sha512()) != 1) - return 0; - break; - case ALG_ECDSAP256SHA256: - if (EVP_VerifyInit(&d->ctx, EVP_sha256()) != 1) - return 0; - break; - case ALG_ECDSAP384SHA384: - if (EVP_VerifyInit(&d->ctx, EVP_sha384()) != 1) - return 0; - break; - default: - return 0; - } - - chunk = rrsig_wirerdata_ex(&d->rr->rr, 0); - if (chunk.length < 0) - return 0; - EVP_VerifyUpdate(&d->ctx, chunk.data, chunk.length); - - set = getmem_temp(sizeof(*set) * signed_set->count); - - signed_rr = signed_set->tail; - i = 0; - while (signed_rr) { - set[i].rr = signed_rr; - set[i].wired = call_get_wired(signed_rr); - if (set[i].wired.length < 0) - return 0; - i++; - signed_rr = signed_rr->next; - } - qsort(set, signed_set->count, sizeof(*set), compare_rr_with_wired); - - for (i = 0; i < signed_set->count; i++) { - chunk = name2wire_name(signed_set->named_rr->name); - if (chunk.length < 0) - return 0; - EVP_VerifyUpdate(&d->ctx, chunk.data, chunk.length); - b2 = htons(set[i].rr->rdtype); EVP_VerifyUpdate(&d->ctx, &b2, 2); - b2 = htons(1); /* class IN */ EVP_VerifyUpdate(&d->ctx, &b2, 2); - b4 = htonl(set[i].rr->ttl); EVP_VerifyUpdate(&d->ctx, &b4, 4); - b2 = htons(set[i].wired.length); EVP_VerifyUpdate(&d->ctx, &b2, 2); - EVP_VerifyUpdate(&d->ctx, set[i].wired.data, set[i].wired.length); - } - - schedule_verification(d); - return 1; + uint16_t b2; + uint32_t b4; + struct binary_data chunk; + struct rr_with_wired *set; + struct rr *signed_rr; + int i; + + EVP_MD_CTX_init(&d->ctx); + switch (d->rr->algorithm) { + case ALG_DSA: + case ALG_RSASHA1: + case ALG_DSA_NSEC3_SHA1: + case ALG_RSASHA1_NSEC3_SHA1: + if (EVP_VerifyInit(&d->ctx, EVP_sha1()) != 1) + return 0; + break; + case ALG_RSASHA256: + if (EVP_VerifyInit(&d->ctx, EVP_sha256()) != 1) + return 0; + break; + case ALG_RSASHA512: + if (EVP_VerifyInit(&d->ctx, EVP_sha512()) != 1) + return 0; + break; + case ALG_ECDSAP256SHA256: + if (EVP_VerifyInit(&d->ctx, EVP_sha256()) != 1) + return 0; + break; + case ALG_ECDSAP384SHA384: + if (EVP_VerifyInit(&d->ctx, EVP_sha384()) != 1) + return 0; + break; + default: + return 0; + } + + chunk = rrsig_wirerdata_ex(&d->rr->rr, 0); + if (chunk.length < 0) + return 0; + EVP_VerifyUpdate(&d->ctx, chunk.data, chunk.length); + + set = getmem_temp(sizeof(*set) * signed_set->count); + + signed_rr = signed_set->tail; + i = 0; + while (signed_rr) { + set[i].rr = signed_rr; + set[i].wired = call_get_wired(signed_rr); + if (set[i].wired.length < 0) + return 0; + i++; + signed_rr = signed_rr->next; + } + qsort(set, signed_set->count, sizeof(*set), compare_rr_with_wired); + + for (i = 0; i < signed_set->count; i++) { + chunk = name2wire_name(signed_set->named_rr->name); + if (chunk.length < 0) + return 0; + EVP_VerifyUpdate(&d->ctx, chunk.data, chunk.length); + b2 = htons(set[i].rr->rdtype); EVP_VerifyUpdate(&d->ctx, &b2, 2); + b2 = htons(1); /* class IN */ EVP_VerifyUpdate(&d->ctx, &b2, 2); + b4 = htonl(set[i].rr->ttl); EVP_VerifyUpdate(&d->ctx, &b4, 4); + b2 = htons(set[i].wired.length); EVP_VerifyUpdate(&d->ctx, &b2, 2); + EVP_VerifyUpdate(&d->ctx, set[i].wired.data, set[i].wired.length); + } + + schedule_verification(d); + return 1; } static void *rrsig_validate(struct rr *rrv) { - RRCAST(rrsig); - struct named_rr *named_rr; - struct rr_set *signed_set; - struct rr_dnskey *key = NULL; - struct rr_set *dnskey_rr_set; - int candidate_keys = 0; - struct keys_to_verify *candidates; - int i = 0; - int t; - - named_rr = rr->rr.rr_set->named_rr; - for (t = 0; t < G.opt.n_times_to_check; t++) { - if (G.opt.times_to_check[t] < rr->sig_inception) { - return moan(rr->rr.file_name, rr->rr.line, "%s signature is too new", named_rr->name); - } - if (G.opt.times_to_check[t] > rr->sig_expiration) { - return moan(rr->rr.file_name, rr->rr.line, "%s signature is too old", named_rr->name); - } - } - signed_set = find_rr_set_in_named_rr(named_rr, rr->type_covered); - if (!signed_set) { - return moan(rr->rr.file_name, rr->rr.line, "%s RRSIG exists for non-existing type %s", named_rr->name, rdtype2str(rr->type_covered)); - } - if (signed_set->tail->ttl != rr->orig_ttl) { - return moan(rr->rr.file_name, rr->rr.line, "%s RRSIG's original TTL differs from corresponding record's", named_rr->name); - } - dnskey_rr_set = find_rr_set(T_DNSKEY, rr->signer); - if (!dnskey_rr_set) { - return moan(rr->rr.file_name, rr->rr.line, "%s RRSIG(%s): cannot find a signer key (%s)", named_rr->name, rdtype2str(rr->type_covered), rr->signer); - } - key = (struct rr_dnskey *)dnskey_rr_set->tail; - while (key) { - if (key->algorithm == rr->algorithm && key->key_tag == rr->key_tag) { - candidate_keys++; - dnskey_build_pkey(key); - } - key = (struct rr_dnskey *)key->rr.next; - } - if (candidate_keys == 0) - return moan(rr->rr.file_name, rr->rr.line, "%s RRSIG(%s): cannot find the right signer key (%s)", named_rr->name, rdtype2str(rr->type_covered), rr->signer); - - candidates = getmem(sizeof(struct keys_to_verify) + (candidate_keys-1) * sizeof(struct verification_data)); - candidates->next = all_keys_to_verify; - candidates->rr = rr; - candidates->signed_set = signed_set; - candidates->n_keys = candidate_keys; - all_keys_to_verify = candidates; - key = (struct rr_dnskey *)dnskey_rr_set->tail; - while (key) { - if (key->algorithm == rr->algorithm && key->key_tag == rr->key_tag) { - candidates->to_verify[i].key = key; - candidates->to_verify[i].rr = rr; - candidates->to_verify[i].ok = 0; - candidates->to_verify[i].openssl_error = 0; - candidates->to_verify[i].next = NULL; - i++; - } - key = (struct rr_dnskey *)key->rr.next; - } - - return rr; + RRCAST(rrsig); + struct named_rr *named_rr; + struct rr_set *signed_set; + struct rr_dnskey *key = NULL; + struct rr_set *dnskey_rr_set; + int candidate_keys = 0; + struct keys_to_verify *candidates; + int i = 0; + int t; + + named_rr = rr->rr.rr_set->named_rr; + for (t = 0; t < G.opt.n_times_to_check; t++) { + if (G.opt.times_to_check[t] < rr->sig_inception) { + return moan(rr->rr.file_name, rr->rr.line, "%s signature is too new", named_rr->name); + } + if (G.opt.times_to_check[t] > rr->sig_expiration) { + return moan(rr->rr.file_name, rr->rr.line, "%s signature is too old", named_rr->name); + } + } + signed_set = find_rr_set_in_named_rr(named_rr, rr->type_covered); + if (!signed_set) { + return moan(rr->rr.file_name, rr->rr.line, "%s RRSIG exists for non-existing type %s", named_rr->name, rdtype2str(rr->type_covered)); + } + if (signed_set->tail->ttl != rr->orig_ttl) { + return moan(rr->rr.file_name, rr->rr.line, "%s RRSIG's original TTL differs from corresponding record's", named_rr->name); + } + dnskey_rr_set = find_rr_set(T_DNSKEY, rr->signer); + if (!dnskey_rr_set) { + return moan(rr->rr.file_name, rr->rr.line, "%s RRSIG(%s): cannot find a signer key (%s)", named_rr->name, rdtype2str(rr->type_covered), rr->signer); + } + key = (struct rr_dnskey *)dnskey_rr_set->tail; + while (key) { + if (key->algorithm == rr->algorithm && key->key_tag == rr->key_tag) { + candidate_keys++; + dnskey_build_pkey(key); + } + key = (struct rr_dnskey *)key->rr.next; + } + if (candidate_keys == 0) + return moan(rr->rr.file_name, rr->rr.line, "%s RRSIG(%s): cannot find the right signer key (%s)", named_rr->name, rdtype2str(rr->type_covered), rr->signer); + + candidates = getmem(sizeof(struct keys_to_verify) + (candidate_keys-1) * sizeof(struct verification_data)); + candidates->next = all_keys_to_verify; + candidates->rr = rr; + candidates->signed_set = signed_set; + candidates->n_keys = candidate_keys; + all_keys_to_verify = candidates; + key = (struct rr_dnskey *)dnskey_rr_set->tail; + while (key) { + if (key->algorithm == rr->algorithm && key->key_tag == rr->key_tag) { + candidates->to_verify[i].key = key; + candidates->to_verify[i].rr = rr; + candidates->to_verify[i].ok = 0; + candidates->to_verify[i].openssl_error = 0; + candidates->to_verify[i].next = NULL; + i++; + } + key = (struct rr_dnskey *)key->rr.next; + } + + return rr; } static pthread_mutex_t *lock_cs; @@ -401,86 +401,86 @@ static long *lock_count; static unsigned long pthreads_thread_id(void) { - unsigned long ret; + unsigned long ret; - ret=(unsigned long)pthread_self(); - return(ret); + ret=(unsigned long)pthread_self(); + return(ret); } static void pthreads_locking_callback(int mode, int type, char *file, int line) { - if (mode & CRYPTO_LOCK) { - pthread_mutex_lock(&(lock_cs[type])); - lock_count[type]++; - } else { - pthread_mutex_unlock(&(lock_cs[type])); - } + if (mode & CRYPTO_LOCK) { + pthread_mutex_lock(&(lock_cs[type])); + lock_count[type]++; + } else { + pthread_mutex_unlock(&(lock_cs[type])); + } } void verify_all_keys(void) { - struct keys_to_verify *k = all_keys_to_verify; - int i; - struct timespec sleep_time; - - ERR_load_crypto_strings(); - if (G.opt.n_threads > 1) { - lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t)); - lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long)); - for (i = 0; i < CRYPTO_num_locks(); i++) { - lock_count[i] = 0; - pthread_mutex_init(&lock_cs[i],NULL); - } - - CRYPTO_set_id_callback((unsigned long (*)())pthreads_thread_id); - CRYPTO_set_locking_callback((void (*)())pthreads_locking_callback); - - if (pthread_mutex_init(&queue_lock, NULL) != 0) - croak(1, "pthread_mutex_init"); - } - - while (k) { - freeall_temp(); - for (i = 0; i < k->n_keys; i++) { - if (dnskey_build_pkey(k->to_verify[i].key)) - verify_signature(&k->to_verify[i], k->signed_set); - } - k = k->next; - } - start_workers(); /* this is needed in case n_threads is greater than the number of signatures to verify */ - while (verification_queue_size > 0) { - sleep_time.tv_sec = 0; - sleep_time.tv_nsec = 10000000; - nanosleep(&sleep_time, NULL); - } - k = all_keys_to_verify; - while (k) { - int ok = 0; - unsigned long e = 0; - for (i = 0; i < k->n_keys; i++) { - if (k->to_verify[i].ok) { - if (k->to_verify[i].rr->rr.rr_set->named_rr->flags & NAME_FLAG_APEX) { - if (k->to_verify[i].key->key_type == KEY_TYPE_UNUSED) - k->to_verify[i].key->key_type = KEY_TYPE_KSK; - } else { - k->to_verify[i].key->key_type = KEY_TYPE_ZSK; - } - ok = 1; - break; - } else { - if (k->to_verify[i].openssl_error != 0) - e = k->to_verify[i].openssl_error; - } - } - if (!ok) { - struct named_rr *named_rr; - named_rr = k->rr->rr.rr_set->named_rr; - moan(k->rr->rr.file_name, k->rr->rr.line, "%s RRSIG(%s): %s", - named_rr->name, rdtype2str(k->rr->type_covered), - e ? ERR_reason_error_string(e) : "cannot verify signature, reason unknown"); - } - k = k->next; - } + struct keys_to_verify *k = all_keys_to_verify; + int i; + struct timespec sleep_time; + + ERR_load_crypto_strings(); + if (G.opt.n_threads > 1) { + lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t)); + lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long)); + for (i = 0; i < CRYPTO_num_locks(); i++) { + lock_count[i] = 0; + pthread_mutex_init(&lock_cs[i],NULL); + } + + CRYPTO_set_id_callback((unsigned long (*)())pthreads_thread_id); + CRYPTO_set_locking_callback((void (*)())pthreads_locking_callback); + + if (pthread_mutex_init(&queue_lock, NULL) != 0) + croak(1, "pthread_mutex_init"); + } + + while (k) { + freeall_temp(); + for (i = 0; i < k->n_keys; i++) { + if (dnskey_build_pkey(k->to_verify[i].key)) + verify_signature(&k->to_verify[i], k->signed_set); + } + k = k->next; + } + start_workers(); /* this is needed in case n_threads is greater than the number of signatures to verify */ + while (verification_queue_size > 0) { + sleep_time.tv_sec = 0; + sleep_time.tv_nsec = 10000000; + nanosleep(&sleep_time, NULL); + } + k = all_keys_to_verify; + while (k) { + int ok = 0; + unsigned long e = 0; + for (i = 0; i < k->n_keys; i++) { + if (k->to_verify[i].ok) { + if (k->to_verify[i].rr->rr.rr_set->named_rr->flags & NAME_FLAG_APEX) { + if (k->to_verify[i].key->key_type == KEY_TYPE_UNUSED) + k->to_verify[i].key->key_type = KEY_TYPE_KSK; + } else { + k->to_verify[i].key->key_type = KEY_TYPE_ZSK; + } + ok = 1; + break; + } else { + if (k->to_verify[i].openssl_error != 0) + e = k->to_verify[i].openssl_error; + } + } + if (!ok) { + struct named_rr *named_rr; + named_rr = k->rr->rr.rr_set->named_rr; + moan(k->rr->rr.file_name, k->rr->rr.line, "%s RRSIG(%s): %s", + named_rr->name, rdtype2str(k->rr->type_covered), + e ? ERR_reason_error_string(e) : "cannot verify signature, reason unknown"); + } + k = k->next; + } } struct rr_methods rrsig_methods = { rrsig_parse, rrsig_human, rrsig_wirerdata, NULL, rrsig_validate }; diff --git a/rt.c b/rt.c index 3bb53bf..41a55ac 100644 --- a/rt.c +++ b/rt.c @@ -19,38 +19,38 @@ static struct rr *rt_parse(char *name, long ttl, int type, char *s) { - struct rr_rt *rr = getmem(sizeof(*rr)); + struct rr_rt *rr = getmem(sizeof(*rr)); - rr->preference = extract_integer(&s, "RT preference", NULL); - if (rr->preference < 0) - return NULL; + rr->preference = extract_integer(&s, "RT preference", NULL); + if (rr->preference < 0) + return NULL; - rr->intermediate_host = extract_name(&s, "intermediate-host", 0); - if (!rr->intermediate_host) - return NULL; - if (*s) { - return bitch("garbage after valid RT data"); - } + rr->intermediate_host = extract_name(&s, "intermediate-host", 0); + if (!rr->intermediate_host) + return NULL; + if (*s) { + return bitch("garbage after valid RT data"); + } - return store_record(type, name, ttl, rr); + return store_record(type, name, ttl, rr); } static char* rt_human(struct rr *rrv) { - RRCAST(rt); + RRCAST(rt); char s[1024]; snprintf(s, 1024, "%d %s", - rr->preference, rr->intermediate_host); + rr->preference, rr->intermediate_host); return quickstrdup_temp(s); } static struct binary_data rt_wirerdata(struct rr *rrv) { - RRCAST(rt); + RRCAST(rt); return compose_binary_data("2d", 1, - rr->preference, name2wire_name(rr->intermediate_host)); + rr->preference, name2wire_name(rr->intermediate_host)); } struct rr_methods rt_methods = { rt_parse, rt_human, rt_wirerdata, NULL, NULL }; diff --git a/soa.c b/soa.c index 028464e..eb0b587 100644 --- a/soa.c +++ b/soa.c @@ -20,64 +20,64 @@ static struct rr* soa_parse(char *name, long ttl, int type, char *s) { - struct rr_soa *rr = getmem(sizeof(*rr)); - long long i; + struct rr_soa *rr = getmem(sizeof(*rr)); + long long i; - rr->mname = extract_name(&s, "mname", 0); - if (!rr->mname) return NULL; - rr->rname = extract_name(&s, "rname", 0); - if (!rr->rname) return NULL; - i = extract_integer(&s, "serial", NULL); - if (i < 0) return NULL; - if (i > 4294967295UL) return bitch("serial is out of range"); - rr->serial = i; - rr->refresh = extract_timevalue(&s, "refresh"); - if (rr->refresh < 0) return NULL; - rr->retry = extract_timevalue(&s, "retry"); - if (rr->retry < 0) return NULL; - rr->expire = extract_timevalue(&s, "expire"); - if (rr->expire < 0) return NULL; - rr->minimum = extract_timevalue(&s, "minimum"); - if (rr->minimum < 0) return NULL; - if (ttl < 0 && G.opt.soa_minttl_as_default_ttl) { - ttl = rr->minimum; - } - if (*s) { - return bitch("garbage after valid SOA data"); - } - return store_record(type, name, ttl, rr); + rr->mname = extract_name(&s, "mname", 0); + if (!rr->mname) return NULL; + rr->rname = extract_name(&s, "rname", 0); + if (!rr->rname) return NULL; + i = extract_integer(&s, "serial", NULL); + if (i < 0) return NULL; + if (i > 4294967295UL) return bitch("serial is out of range"); + rr->serial = i; + rr->refresh = extract_timevalue(&s, "refresh"); + if (rr->refresh < 0) return NULL; + rr->retry = extract_timevalue(&s, "retry"); + if (rr->retry < 0) return NULL; + rr->expire = extract_timevalue(&s, "expire"); + if (rr->expire < 0) return NULL; + rr->minimum = extract_timevalue(&s, "minimum"); + if (rr->minimum < 0) return NULL; + if (ttl < 0 && G.opt.soa_minttl_as_default_ttl) { + ttl = rr->minimum; + } + if (*s) { + return bitch("garbage after valid SOA data"); + } + return store_record(type, name, ttl, rr); } static char* soa_human(struct rr *rrv) { - RRCAST(soa); + RRCAST(soa); char s[1024]; snprintf(s, 1024, "%s %s %u %d %d %d %d", - rr->mname, rr->rname, rr->serial, - rr->refresh, rr->retry, rr->expire, rr->minimum); + rr->mname, rr->rname, rr->serial, + rr->refresh, rr->retry, rr->expire, rr->minimum); return quickstrdup_temp(s); } static struct binary_data soa_wirerdata(struct rr *rrv) { - RRCAST(soa); + RRCAST(soa); - return compose_binary_data("dd44444", 1, - name2wire_name(rr->mname), name2wire_name(rr->rname), - rr->serial, rr->refresh, rr->retry, - rr->expire, rr->minimum); + return compose_binary_data("dd44444", 1, + name2wire_name(rr->mname), name2wire_name(rr->rname), + rr->serial, rr->refresh, rr->retry, + rr->expire, rr->minimum); } static void *soa_validate(struct rr *rrv) { - RRCAST(soa); + RRCAST(soa); - if (strchr(rr->mname, '/') != NULL) - return moan(rr->rr.file_name, rr->rr.line, "MNAME contains '/'"); - if (strchr(rr->rname, '/') != NULL) - return moan(rr->rr.file_name, rr->rr.line, "RNAME contains '/'"); - return NULL; + if (strchr(rr->mname, '/') != NULL) + return moan(rr->rr.file_name, rr->rr.line, "MNAME contains '/'"); + if (strchr(rr->rname, '/') != NULL) + return moan(rr->rr.file_name, rr->rr.line, "RNAME contains '/'"); + return NULL; } struct rr_methods soa_methods = { soa_parse, soa_human, soa_wirerdata, NULL, soa_validate }; diff --git a/spf.c b/spf.c index 0c6b46e..c8e564a 100644 --- a/spf.c +++ b/spf.c @@ -19,70 +19,70 @@ /* XXX * We need to add the following spf-specific policy checks: - * - record not too long (DNS name + length of SPF+TXT < 450) - rfc4408, 3.1.4 - * - record should match /^v=spf1( |$)/ - rfc4408, 4.5 - * - maybe check for other syntax features - * - there should be an identical TXT record - rfc4408, 3.1.1 - * - there should only be one SPF per DNS name - rfc4408, 4.5 + * - record not too long (DNS name + length of SPF+TXT < 450) - rfc4408, 3.1.4 + * - record should match /^v=spf1( |$)/ - rfc4408, 4.5 + * - maybe check for other syntax features + * - there should be an identical TXT record - rfc4408, 3.1.1 + * - there should only be one SPF per DNS name - rfc4408, 4.5 */ static struct rr *spf_parse(char *name, long ttl, int type, char *s) { - struct rr_spf *rr; - struct binary_data spf[20]; - int i; + struct rr_spf *rr; + struct binary_data spf[20]; + int i; - i = 0; - while (*s) { - if (i >= 20) - return bitch("program limit: too many SPF text segments"); - spf[i] = extract_text(&s, "SPF text segment"); - if (spf[i].length < 0) - return NULL; - if (spf[i].length > 255) - return bitch("SPF segment too long"); - i++; - } - if (i == 0) - return bitch("empty text record"); + i = 0; + while (*s) { + if (i >= 20) + return bitch("program limit: too many SPF text segments"); + spf[i] = extract_text(&s, "SPF text segment"); + if (spf[i].length < 0) + return NULL; + if (spf[i].length > 255) + return bitch("SPF segment too long"); + i++; + } + if (i == 0) + return bitch("empty text record"); - rr = getmem(sizeof(*rr) + sizeof(struct binary_data) * (i-1)); - rr->count = i; - for (i = 0; i < rr->count; i++) { - rr->spf[i] = spf[i]; - } + rr = getmem(sizeof(*rr) + sizeof(struct binary_data) * (i-1)); + rr->count = i; + for (i = 0; i < rr->count; i++) { + rr->spf[i] = spf[i]; + } - return store_record(type, name, ttl, rr); + return store_record(type, name, ttl, rr); } static char* spf_human(struct rr *rrv) { - RRCAST(spf); + RRCAST(spf); char ss[1024]; - int i; - char *s = ss; - int l; + int i; + char *s = ss; + int l; - for (i = 0; i < rr->count; i++) { - l = snprintf(s, 1024-(s-ss), "\"%s\" ", rr->spf[i].data); - s += l; - } + for (i = 0; i < rr->count; i++) { + l = snprintf(s, 1024-(s-ss), "\"%s\" ", rr->spf[i].data); + s += l; + } return quickstrdup_temp(ss); } static struct binary_data spf_wirerdata(struct rr *rrv) { - RRCAST(spf); - struct binary_data r, t; - int i; + RRCAST(spf); + struct binary_data r, t; + int i; - r = bad_binary_data(); - t.length = 0; - t.data = NULL; - for (i = 0; i < rr->count; i++) { - r = compose_binary_data("db", 1, t, rr->spf[i]); - t = r; - } + r = bad_binary_data(); + t.length = 0; + t.data = NULL; + for (i = 0; i < rr->count; i++) { + r = compose_binary_data("db", 1, t, rr->spf[i]); + t = r; + } return r; } diff --git a/srv.c b/srv.c index 808dade..3c154f2 100644 --- a/srv.c +++ b/srv.c @@ -19,60 +19,60 @@ static struct rr *srv_parse(char *name, long ttl, int type, char *s) { - struct rr_srv *rr = getmem(sizeof(*rr)); - int i; + struct rr_srv *rr = getmem(sizeof(*rr)); + int i; - /* TODO validate `name` (underscores etc) http://tools.ietf.org/html/rfc2782 */ + /* TODO validate `name` (underscores etc) http://tools.ietf.org/html/rfc2782 */ - i = extract_integer(&s, "priority", NULL); - if (i < 0) - return NULL; - if (i >= 65536) - return bitch("priority range is not valid"); - rr->priority = i; + i = extract_integer(&s, "priority", NULL); + if (i < 0) + return NULL; + if (i >= 65536) + return bitch("priority range is not valid"); + rr->priority = i; - i = extract_integer(&s, "weight", NULL); - if (i < 0) - return NULL; - if (i >= 65536) - return bitch("weight range is not valid"); - rr->weight = i; + i = extract_integer(&s, "weight", NULL); + if (i < 0) + return NULL; + if (i >= 65536) + return bitch("weight range is not valid"); + rr->weight = i; - i = extract_integer(&s, "port", NULL); - if (i < 0) - return NULL; - if (i >= 65536) - return bitch("port range is not valid"); - rr->port = i; + i = extract_integer(&s, "port", NULL); + if (i < 0) + return NULL; + if (i >= 65536) + return bitch("port range is not valid"); + rr->port = i; - rr->target = extract_name(&s, "target", 0); - if (!rr->target) - return NULL; + rr->target = extract_name(&s, "target", 0); + if (!rr->target) + return NULL; - if (*s) { - return bitch("garbage after valid SRV data"); - } + if (*s) { + return bitch("garbage after valid SRV data"); + } - return store_record(type, name, ttl, rr); + return store_record(type, name, ttl, rr); } static char* srv_human(struct rr *rrv) { - RRCAST(srv); + RRCAST(srv); char s[1024]; - snprintf(s, 1024, "%hu %hu %hu %s", - rr->priority, rr->weight, rr->port, rr->target); + snprintf(s, 1024, "%hu %hu %hu %s", + rr->priority, rr->weight, rr->port, rr->target); - return quickstrdup_temp(s); + return quickstrdup_temp(s); } static struct binary_data srv_wirerdata(struct rr *rrv) { - RRCAST(srv); + RRCAST(srv); return compose_binary_data("222d", 1, - rr->priority, rr->weight, rr->port, - name2wire_name(rr->target)); + rr->priority, rr->weight, rr->port, + name2wire_name(rr->target)); } struct rr_methods srv_methods = { srv_parse, srv_human, srv_wirerdata, NULL, NULL }; diff --git a/sshfp.c b/sshfp.c index 55b78f3..67fe236 100644 --- a/sshfp.c +++ b/sshfp.c @@ -19,63 +19,63 @@ static struct rr* sshfp_parse(char *name, long ttl, int type, char *s) { - struct rr_sshfp *rr = getmem(sizeof(*rr)); - int algorithm, fp_type; + struct rr_sshfp *rr = getmem(sizeof(*rr)); + int algorithm, fp_type; - algorithm = extract_integer(&s, "algorithm", NULL); - if (algorithm < 0) return NULL; - if (algorithm != 1 && algorithm != 2 && algorithm != 3 && algorithm != 4) - return bitch("unsupported algorithm"); - rr->algorithm = algorithm; + algorithm = extract_integer(&s, "algorithm", NULL); + if (algorithm < 0) return NULL; + if (algorithm != 1 && algorithm != 2 && algorithm != 3 && algorithm != 4) + return bitch("unsupported algorithm"); + rr->algorithm = algorithm; - fp_type = extract_integer(&s, "fp type", NULL); - if (fp_type < 0) return NULL; - if (fp_type != 1 && fp_type != 2) - return bitch("unsupported fp_type"); - rr->fp_type = fp_type; + fp_type = extract_integer(&s, "fp type", NULL); + if (fp_type < 0) return NULL; + if (fp_type != 1 && fp_type != 2) + return bitch("unsupported fp_type"); + rr->fp_type = fp_type; - rr->fingerprint = extract_hex_binary_data(&s, "fingerprint", EXTRACT_EAT_WHITESPACE); - if (rr->fingerprint.length < 0) return NULL; - - if (rr->fp_type == 1 && rr->fingerprint.length != SHA1_BYTES) { - return bitch("wrong SHA-1 fingerprint length: %d bytes found, %d bytes expected", - rr->fingerprint.length, SHA1_BYTES); - } - if (rr->fp_type == 2 && rr->fingerprint.length != SHA256_BYTES) { - return bitch("wrong SHA-256 fingerprint length: %d bytes found, %d bytes expected", - rr->fingerprint.length, SHA256_BYTES); - } + rr->fingerprint = extract_hex_binary_data(&s, "fingerprint", EXTRACT_EAT_WHITESPACE); + if (rr->fingerprint.length < 0) return NULL; + + if (rr->fp_type == 1 && rr->fingerprint.length != SHA1_BYTES) { + return bitch("wrong SHA-1 fingerprint length: %d bytes found, %d bytes expected", + rr->fingerprint.length, SHA1_BYTES); + } + if (rr->fp_type == 2 && rr->fingerprint.length != SHA256_BYTES) { + return bitch("wrong SHA-256 fingerprint length: %d bytes found, %d bytes expected", + rr->fingerprint.length, SHA256_BYTES); + } - if (*s) { - return bitch("garbage after valid SSHFP data"); - } - return store_record(type, name, ttl, rr); + if (*s) { + return bitch("garbage after valid SSHFP data"); + } + return store_record(type, name, ttl, rr); } static char* sshfp_human(struct rr *rrv) { - RRCAST(sshfp); + RRCAST(sshfp); char ss[4096]; - char *s = ss; - int l; - int i; + char *s = ss; + int l; + int i; l = snprintf(s, 4096, "%u %u ", rr->algorithm, rr->fp_type); - s += l; - for (i = 0; i < rr->fingerprint.length; i++) { - l = snprintf(s, 4096-(s-ss), "%02X", (unsigned char)rr->fingerprint.data[i]); - s += l; - } + s += l; + for (i = 0; i < rr->fingerprint.length; i++) { + l = snprintf(s, 4096-(s-ss), "%02X", (unsigned char)rr->fingerprint.data[i]); + s += l; + } return quickstrdup_temp(ss); } static struct binary_data sshfp_wirerdata(struct rr *rrv) { - RRCAST(sshfp); + RRCAST(sshfp); - return compose_binary_data("11d", 1, - rr->algorithm, rr->fp_type, - rr->fingerprint); + return compose_binary_data("11d", 1, + rr->algorithm, rr->fp_type, + rr->fingerprint); } struct rr_methods sshfp_methods = { sshfp_parse, sshfp_human, sshfp_wirerdata, NULL, NULL }; diff --git a/textparse.c b/textparse.c index 21f622e..67e44a8 100644 --- a/textparse.c +++ b/textparse.c @@ -26,1014 +26,1014 @@ int empty_line_or_comment(char *s) { - while (isspace(*s)) s++; - if (!*s) return 1; - if (*s == ';') return 1; - return 0; + while (isspace(*s)) s++; + if (!*s) return 1; + if (*s == ';') return 1; + return 0; } char *skip_white_space(char *s) { - while (isspace(*s)) s++; - if (*s == ';') { - while (*s) s++; - } - if (*s == 0) { - if (file_info->paren_mode) { - if (read_zone_line()) { - return skip_white_space(file_info->buf); - } else { - return bitch("unexpected end of file"); - } - } - } - if (*s == '(') { - if (file_info->paren_mode) { - return bitch("unexpected opening parenthesis"); - } else { - file_info->paren_mode = 1; - s++; - return skip_white_space(s); - } - } - if (*s == ')') { - if (file_info->paren_mode) { - file_info->paren_mode = 0; - s++; - return skip_white_space(s); - } else { - return bitch("unexpected closing parenthesis"); - } - } - return s; + while (isspace(*s)) s++; + if (*s == ';') { + while (*s) s++; + } + if (*s == 0) { + if (file_info->paren_mode) { + if (read_zone_line()) { + return skip_white_space(file_info->buf); + } else { + return bitch("unexpected end of file"); + } + } + } + if (*s == '(') { + if (file_info->paren_mode) { + return bitch("unexpected opening parenthesis"); + } else { + file_info->paren_mode = 1; + s++; + return skip_white_space(s); + } + } + if (*s == ')') { + if (file_info->paren_mode) { + file_info->paren_mode = 0; + s++; + return skip_white_space(s); + } else { + return bitch("unexpected closing parenthesis"); + } + } + return s; } static char *extract_name_slow(char **input, char *what, int options) { - char buf[1024]; - char *t = buf; - char *s = *input; - int d, l, ol; - - while (1) { - if (isalnum(*s) || *s == '_' || *s == '.' || *s == '-' || *s == '/' || ((options & DOLLAR_OK_IN_NAMES) && *s == '$')) { - if (t-buf >= 1022) - return bitch("name too long"); - *t++ = *s++; - } else if (*s == '\\') { - s++; - if (isdigit(*s)) { - d = *s - '0'; - s++; - if (!isdigit(*s)) - return bitch("bad escape sequence"); - d = d*10 + *s - '0'; - s++; - if (!isdigit(*s)) - return bitch("bad escape sequence"); - d = d*10 + *s - '0'; - s++; - if (d > 255) - return bitch("bad escape sequence"); - if (d == '.') - return bitch("a dot within a label is not currently supported"); - *((unsigned char *)t) = (unsigned char)d; - if (t-buf >= 1022) - return bitch("name too long"); - t++; - } else if (*s == '.') { - return bitch("a dot within a label is not currently supported"); - } else if (*s) { - if (t-buf >= 1022) - return bitch("name too long"); - *t++ = *s++; - } else { - return bitch("backslash in the end of the line not parsable"); - } - } else { - break; - } - } - if (*s && !isspace(*s) && *s != ';' && *s != ')') { - return bitch("%s is not valid", what); - } - *t = '\0'; - - l = strlen(buf); - if (!l) - return bitch("%s should not be empty", what); - - if (buf[l-1] != '.') { - if (!file_info->current_origin) { - return bitch("do not know origin to determine %s", what); - } - ol = strlen(file_info->current_origin); - if (file_info->current_origin[0] == '.') { - if (l + ol >= 1023) - return bitch("name too long"); - strcat(buf, file_info->current_origin); - } else { - if (l + ol >= 1022) - return bitch("name too long"); - strcat(buf, "."); - strcat(buf, file_info->current_origin); - } - } - - t = strchr(buf, '*'); - if (t && (t != buf || t[1] != '.')) - return bitch("%s: bad wildcard", what); - if (buf[0] == '.' && buf[1] != '\0') - return bitch("%s: name cannot start with a dot", what); - if (strstr(buf, "..")) - return bitch("%s: empty label in a name", what); - - *input = skip_white_space(s); - if (!*input) - return NULL; /* bitching's done elsewhere */ - if (!(options & KEEP_CAPITALIZATION)) { - t = buf; - while (*t) { - *t = tolower(*t); - t++; - } - } - - t = quickstrdup(buf); - return t; + char buf[1024]; + char *t = buf; + char *s = *input; + int d, l, ol; + + while (1) { + if (isalnum(*s) || *s == '_' || *s == '.' || *s == '-' || *s == '/' || ((options & DOLLAR_OK_IN_NAMES) && *s == '$')) { + if (t-buf >= 1022) + return bitch("name too long"); + *t++ = *s++; + } else if (*s == '\\') { + s++; + if (isdigit(*s)) { + d = *s - '0'; + s++; + if (!isdigit(*s)) + return bitch("bad escape sequence"); + d = d*10 + *s - '0'; + s++; + if (!isdigit(*s)) + return bitch("bad escape sequence"); + d = d*10 + *s - '0'; + s++; + if (d > 255) + return bitch("bad escape sequence"); + if (d == '.') + return bitch("a dot within a label is not currently supported"); + *((unsigned char *)t) = (unsigned char)d; + if (t-buf >= 1022) + return bitch("name too long"); + t++; + } else if (*s == '.') { + return bitch("a dot within a label is not currently supported"); + } else if (*s) { + if (t-buf >= 1022) + return bitch("name too long"); + *t++ = *s++; + } else { + return bitch("backslash in the end of the line not parsable"); + } + } else { + break; + } + } + if (*s && !isspace(*s) && *s != ';' && *s != ')') { + return bitch("%s is not valid", what); + } + *t = '\0'; + + l = strlen(buf); + if (!l) + return bitch("%s should not be empty", what); + + if (buf[l-1] != '.') { + if (!file_info->current_origin) { + return bitch("do not know origin to determine %s", what); + } + ol = strlen(file_info->current_origin); + if (file_info->current_origin[0] == '.') { + if (l + ol >= 1023) + return bitch("name too long"); + strcat(buf, file_info->current_origin); + } else { + if (l + ol >= 1022) + return bitch("name too long"); + strcat(buf, "."); + strcat(buf, file_info->current_origin); + } + } + + t = strchr(buf, '*'); + if (t && (t != buf || t[1] != '.')) + return bitch("%s: bad wildcard", what); + if (buf[0] == '.' && buf[1] != '\0') + return bitch("%s: name cannot start with a dot", what); + if (strstr(buf, "..")) + return bitch("%s: empty label in a name", what); + + *input = skip_white_space(s); + if (!*input) + return NULL; /* bitching's done elsewhere */ + if (!(options & KEEP_CAPITALIZATION)) { + t = buf; + while (*t) { + *t = tolower(*t); + t++; + } + } + + t = quickstrdup(buf); + return t; } char *extract_name(char **input, char *what, int options) { - char *s = *input; - char *r = NULL; - char *end = NULL; - char c; - int wildcard = 0; - - if (*s == '@') { - s++; - if (*s && !isspace(*s) && *s != ';' && *s != ')') { - return bitch("literal @ in %s is not all by itself", what); - } - if (!file_info->current_origin) { - return bitch("do not know origin to expand @ in %s", what); - } - r = quickstrdup(file_info->current_origin); - } else { - if (!(isalnum(*s) || *s == '_' || *s == '.' || *s == '/' || ((options & DOLLAR_OK_IN_NAMES) && *s == '$'))) { - if (*s == '*') { - wildcard = 1; - } else { - if (*s == '\\') - return extract_name_slow(input, what, options); - return bitch("%s expected", what); - } - } - s++; - while (isalnum(*s) || *s == '.' || *s == '-' || *s == '_' || *s == '/' || ((options & DOLLAR_OK_IN_NAMES) && *s == '$')) - s++; - if (*s && !isspace(*s) && *s != ';' && *s != ')') { - if (*s == '\\') - return extract_name_slow(input, what, options); - return bitch("%s is not valid", what); - } - if (!*s) end = s; - c = *s; - *s = '\0'; - if (*(s-1) == '.') { - r = quickstrdup(*input); - } else { - if (!file_info->current_origin) { - return bitch("do not know origin to determine %s", what); - } - r = getmem(strlen(*input) + 1 + strlen(file_info->current_origin) + 1); - if (file_info->current_origin[0] == '.') { - strcpy(mystpcpy(r, *input), file_info->current_origin); - } else { - strcpy(mystpcpy(mystpcpy(r, *input), "."), file_info->current_origin); - } - } - *s = c; - } - if (end) { - *input = end; - } else { - *input = skip_white_space(s); - if (!*input) - return NULL; /* bitching's done elsewhere */ - } - if (!(options & KEEP_CAPITALIZATION)) { - s = r; - while (*s) { - *s = tolower(*s); - s++; - } - } - if (wildcard && r[1] != '.') { - return bitch("%s: bad wildcard", what); - } else if (r[0] == '.' && r[1] != '\0') { - return bitch("%s: name cannot start with a dot", what); - } - return r; + char *s = *input; + char *r = NULL; + char *end = NULL; + char c; + int wildcard = 0; + + if (*s == '@') { + s++; + if (*s && !isspace(*s) && *s != ';' && *s != ')') { + return bitch("literal @ in %s is not all by itself", what); + } + if (!file_info->current_origin) { + return bitch("do not know origin to expand @ in %s", what); + } + r = quickstrdup(file_info->current_origin); + } else { + if (!(isalnum(*s) || *s == '_' || *s == '.' || *s == '/' || ((options & DOLLAR_OK_IN_NAMES) && *s == '$'))) { + if (*s == '*') { + wildcard = 1; + } else { + if (*s == '\\') + return extract_name_slow(input, what, options); + return bitch("%s expected", what); + } + } + s++; + while (isalnum(*s) || *s == '.' || *s == '-' || *s == '_' || *s == '/' || ((options & DOLLAR_OK_IN_NAMES) && *s == '$')) + s++; + if (*s && !isspace(*s) && *s != ';' && *s != ')') { + if (*s == '\\') + return extract_name_slow(input, what, options); + return bitch("%s is not valid", what); + } + if (!*s) end = s; + c = *s; + *s = '\0'; + if (*(s-1) == '.') { + r = quickstrdup(*input); + } else { + if (!file_info->current_origin) { + return bitch("do not know origin to determine %s", what); + } + r = getmem(strlen(*input) + 1 + strlen(file_info->current_origin) + 1); + if (file_info->current_origin[0] == '.') { + strcpy(mystpcpy(r, *input), file_info->current_origin); + } else { + strcpy(mystpcpy(mystpcpy(r, *input), "."), file_info->current_origin); + } + } + *s = c; + } + if (end) { + *input = end; + } else { + *input = skip_white_space(s); + if (!*input) + return NULL; /* bitching's done elsewhere */ + } + if (!(options & KEEP_CAPITALIZATION)) { + s = r; + while (*s) { + *s = tolower(*s); + s++; + } + } + if (wildcard && r[1] != '.') { + return bitch("%s: bad wildcard", what); + } else if (r[0] == '.' && r[1] != '\0') { + return bitch("%s: name cannot start with a dot", what); + } + return r; } char *extract_label(char **input, char *what, void *is_temporary) { - char *s = *input; - char *r = NULL; - char *end = NULL; - - if (!isalpha(*s)) { - return bitch("%s expected", what); - } - s++; - while (isalnum(*s)) - s++; - if (*s && !isspace(*s)) { - return bitch("%s is not valid", what); - } - if (!*s) end = s; - *s++ = '\0'; - if (is_temporary) { - r = quickstrdup_temp(*input); - } else { - r = quickstrdup(*input); - } - - if (end) { - *input = end; - } else { - *input = skip_white_space(s); - if (!*input) - return NULL; /* bitching's done elsewhere */ - } - s = r; - while (*s) { - *s = tolower(*s); - s++; - } - return r; + char *s = *input; + char *r = NULL; + char *end = NULL; + + if (!isalpha(*s)) { + return bitch("%s expected", what); + } + s++; + while (isalnum(*s)) + s++; + if (*s && !isspace(*s)) { + return bitch("%s is not valid", what); + } + if (!*s) end = s; + *s++ = '\0'; + if (is_temporary) { + r = quickstrdup_temp(*input); + } else { + r = quickstrdup(*input); + } + + if (end) { + *input = end; + } else { + *input = skip_white_space(s); + if (!*input) + return NULL; /* bitching's done elsewhere */ + } + s = r; + while (*s) { + *s = tolower(*s); + s++; + } + return r; } long long extract_integer(char **input, char *what, const char *extra_delimiters) { - char *s = *input; - long long r = -1; - char *end = NULL; - char c; - - if (!isdigit(*s)) { - bitch("%s expected", what); - return -1; - } - s++; - while (isdigit(*s)) - s++; - if (*s && !isspace(*s) && *s != ';' && *s != ')') { - if (!extra_delimiters || strchr(extra_delimiters, *s) == NULL) { - bitch("%s is not valid", what); - return -1; - } - } - if (!*s) end = s; - c = *s; - *s = '\0'; - r = strtoll(*input, NULL, 10); - *s = c; - - if (end) { - *input = end; - } else { - *input = skip_white_space(s); - if (!*input) - return -1; /* bitching's done elsewhere */ - } - return r; + char *s = *input; + long long r = -1; + char *end = NULL; + char c; + + if (!isdigit(*s)) { + bitch("%s expected", what); + return -1; + } + s++; + while (isdigit(*s)) + s++; + if (*s && !isspace(*s) && *s != ';' && *s != ')') { + if (!extra_delimiters || strchr(extra_delimiters, *s) == NULL) { + bitch("%s is not valid", what); + return -1; + } + } + if (!*s) end = s; + c = *s; + *s = '\0'; + r = strtoll(*input, NULL, 10); + *s = c; + + if (end) { + *input = end; + } else { + *input = skip_white_space(s); + if (!*input) + return -1; /* bitching's done elsewhere */ + } + return r; } int extract_double(char **input, char *what, double *val, int skip_m) { - char *s = *input; - char *end = NULL; - char *stop; - char c; - int saw_m = 0; - - while (isdigit(*s) || *s == '+' || *s == '-' || *s == '.') - s++; - if (*s && !isspace(*s) && *s != ';' && *s != ')') { - if (skip_m && (*s == 'm' || *s == 'M')) { - saw_m = 1; - } else { - bitch("%s is not valid", what); - return -1; - } - } - if (!*s) end = s; - c = *s; - *s = '\0'; - *val = strtod(*input, &stop); - if (*stop != '\0') { - *s = c; - bitch("%s is not valid", what); - return -1; - } - *s = c; - - if (saw_m) { - s++; - if (*s && !isspace(*s) && *s != ';' && *s != ')') { - bitch("%s is not valid", what); - return -1; - } - } - - if (end) { - *input = end; - } else { - *input = skip_white_space(s); - if (!*input) - return -1; /* bitching's done elsewhere */ - } - return 1; + char *s = *input; + char *end = NULL; + char *stop; + char c; + int saw_m = 0; + + while (isdigit(*s) || *s == '+' || *s == '-' || *s == '.') + s++; + if (*s && !isspace(*s) && *s != ';' && *s != ')') { + if (skip_m && (*s == 'm' || *s == 'M')) { + saw_m = 1; + } else { + bitch("%s is not valid", what); + return -1; + } + } + if (!*s) end = s; + c = *s; + *s = '\0'; + *val = strtod(*input, &stop); + if (*stop != '\0') { + *s = c; + bitch("%s is not valid", what); + return -1; + } + *s = c; + + if (saw_m) { + s++; + if (*s && !isspace(*s) && *s != ';' && *s != ')') { + bitch("%s is not valid", what); + return -1; + } + } + + if (end) { + *input = end; + } else { + *input = skip_white_space(s); + if (!*input) + return -1; /* bitching's done elsewhere */ + } + return 1; } long extract_timevalue(char **input, char *what) { - char *s = *input; - int r = 0, acc = 0; + char *s = *input; + int r = 0, acc = 0; - if (!isdigit(*s)) { - bitch("%s expected", what); - return -1; - } + if (!isdigit(*s)) { + bitch("%s expected", what); + return -1; + } next_component: - r = 0; - while (isdigit(*s)) { - r *= 10; - r += *s - '0'; - s++; - } - if (tolower(*s) == 's') { - s++; - } else if (tolower(*s) == 'm') { - r *= 60; - s++; - } else if (tolower(*s) == 'h') { - r *= 3600; - s++; - } else if (tolower(*s) == 'd') { - r *= 86400; - s++; - } else if (tolower(*s) == 'w') { - r *= 604800; - s++; - } - acc += r; - if (isdigit(*s)) goto next_component; - - if (*s && !isspace(*s) && *s != ';' && *s != ')') { - bitch("%s is not valid", what); - return -1; - } - *input = skip_white_space(s); - if (!*input) - return -1; /* bitching's done elsewhere */ - return acc; + r = 0; + while (isdigit(*s)) { + r *= 10; + r += *s - '0'; + s++; + } + if (tolower(*s) == 's') { + s++; + } else if (tolower(*s) == 'm') { + r *= 60; + s++; + } else if (tolower(*s) == 'h') { + r *= 3600; + s++; + } else if (tolower(*s) == 'd') { + r *= 86400; + s++; + } else if (tolower(*s) == 'w') { + r *= 604800; + s++; + } + acc += r; + if (isdigit(*s)) goto next_component; + + if (*s && !isspace(*s) && *s != ';' && *s != ')') { + bitch("%s is not valid", what); + return -1; + } + *input = skip_white_space(s); + if (!*input) + return -1; /* bitching's done elsewhere */ + return acc; } long long extract_timestamp(char **input, char *what) { - char *s = *input; - int year = 0; - int month = 0; - int day = 0; - int hour = 0; - int minute = 0; - int second = 0; - long long epoch = 0; - struct tm tm; - - if (!isdigit(*s)) { - bitch("%s expected", what); - return -1; - } - year = year*10 + *s - '0'; - epoch = epoch*10 + *s - '0'; - s++; - if (!isdigit(*s)) goto looks_like_epoch; - year = year*10 + *s - '0'; - epoch = epoch*10 + *s - '0'; - s++; - if (!isdigit(*s)) goto looks_like_epoch; - year = year*10 + *s - '0'; - epoch = epoch*10 + *s - '0'; - s++; - if (!isdigit(*s)) goto looks_like_epoch; - year = year*10 + *s - '0'; - epoch = epoch*10 + *s - '0'; - s++; - if (!isdigit(*s)) goto looks_like_epoch; - month = month*10 + *s - '0'; - epoch = epoch*10 + *s - '0'; - s++; - if (!isdigit(*s)) goto looks_like_epoch; - month = month*10 + *s - '0'; - epoch = epoch*10 + *s - '0'; - s++; - if (!isdigit(*s)) goto looks_like_epoch; - day = day*10 + *s - '0'; - epoch = epoch*10 + *s - '0'; - s++; - if (!isdigit(*s)) goto looks_like_epoch; - day = day*10 + *s - '0'; - epoch = epoch*10 + *s - '0'; - s++; - if (!isdigit(*s)) goto looks_like_epoch; - hour = hour*10 + *s - '0'; - epoch = epoch*10 + *s - '0'; - s++; - if (!isdigit(*s)) goto looks_like_epoch; - hour = hour*10 + *s - '0'; - epoch = epoch*10 + *s - '0'; - s++; - if (!isdigit(*s)) goto looks_like_epoch; - minute = minute*10 + *s - '0'; - epoch = epoch*10 + *s - '0'; - s++; - if (!isdigit(*s)) goto looks_like_epoch; - minute = minute*10 + *s - '0'; - epoch = epoch*10 + *s - '0'; - s++; - if (!isdigit(*s)) goto looks_like_epoch; - second = second*10 + *s - '0'; - epoch = epoch*10 + *s - '0'; - s++; - if (!isdigit(*s)) goto looks_like_epoch; - second = second*10 + *s - '0'; - epoch = epoch*10 + *s - '0'; - s++; - if (*s && !isspace(*s) && *s != ';' && *s != ')') { - bitch("%s is not valid", what); - return -1; - } - if (second > 60 || minute > 59 || hour > 23 || day < 1 || day > 31 || - month > 12 || year < 1900 || year > 2037) - { - bitch("%s is not valid", what); - return -1; - } - memset(&tm, 0, sizeof(tm)); - tm.tm_sec = second; - tm.tm_min = minute; - tm.tm_hour = hour; - tm.tm_mday = day; - tm.tm_mon = month - 1; - tm.tm_year = year - 1900; - epoch = mktime(&tm); - if (epoch < 0) { - bitch("%s is not valid", what); - return -1; - } - - goto done; + char *s = *input; + int year = 0; + int month = 0; + int day = 0; + int hour = 0; + int minute = 0; + int second = 0; + long long epoch = 0; + struct tm tm; + + if (!isdigit(*s)) { + bitch("%s expected", what); + return -1; + } + year = year*10 + *s - '0'; + epoch = epoch*10 + *s - '0'; + s++; + if (!isdigit(*s)) goto looks_like_epoch; + year = year*10 + *s - '0'; + epoch = epoch*10 + *s - '0'; + s++; + if (!isdigit(*s)) goto looks_like_epoch; + year = year*10 + *s - '0'; + epoch = epoch*10 + *s - '0'; + s++; + if (!isdigit(*s)) goto looks_like_epoch; + year = year*10 + *s - '0'; + epoch = epoch*10 + *s - '0'; + s++; + if (!isdigit(*s)) goto looks_like_epoch; + month = month*10 + *s - '0'; + epoch = epoch*10 + *s - '0'; + s++; + if (!isdigit(*s)) goto looks_like_epoch; + month = month*10 + *s - '0'; + epoch = epoch*10 + *s - '0'; + s++; + if (!isdigit(*s)) goto looks_like_epoch; + day = day*10 + *s - '0'; + epoch = epoch*10 + *s - '0'; + s++; + if (!isdigit(*s)) goto looks_like_epoch; + day = day*10 + *s - '0'; + epoch = epoch*10 + *s - '0'; + s++; + if (!isdigit(*s)) goto looks_like_epoch; + hour = hour*10 + *s - '0'; + epoch = epoch*10 + *s - '0'; + s++; + if (!isdigit(*s)) goto looks_like_epoch; + hour = hour*10 + *s - '0'; + epoch = epoch*10 + *s - '0'; + s++; + if (!isdigit(*s)) goto looks_like_epoch; + minute = minute*10 + *s - '0'; + epoch = epoch*10 + *s - '0'; + s++; + if (!isdigit(*s)) goto looks_like_epoch; + minute = minute*10 + *s - '0'; + epoch = epoch*10 + *s - '0'; + s++; + if (!isdigit(*s)) goto looks_like_epoch; + second = second*10 + *s - '0'; + epoch = epoch*10 + *s - '0'; + s++; + if (!isdigit(*s)) goto looks_like_epoch; + second = second*10 + *s - '0'; + epoch = epoch*10 + *s - '0'; + s++; + if (*s && !isspace(*s) && *s != ';' && *s != ')') { + bitch("%s is not valid", what); + return -1; + } + if (second > 60 || minute > 59 || hour > 23 || day < 1 || day > 31 || + month > 12 || year < 1900 || year > 2037) + { + bitch("%s is not valid", what); + return -1; + } + memset(&tm, 0, sizeof(tm)); + tm.tm_sec = second; + tm.tm_min = minute; + tm.tm_hour = hour; + tm.tm_mday = day; + tm.tm_mon = month - 1; + tm.tm_year = year - 1900; + epoch = mktime(&tm); + if (epoch < 0) { + bitch("%s is not valid", what); + return -1; + } + + goto done; looks_like_epoch: - if (*s && !isspace(*s) && *s != ';' && *s != ')') { - bitch("%s is not valid", what); - return -1; - } + if (*s && !isspace(*s) && *s != ';' && *s != ')') { + bitch("%s is not valid", what); + return -1; + } done: - *input = skip_white_space(s); - if (!*input) - return -1; /* bitching's done elsewhere */ - return epoch; + *input = skip_white_space(s); + if (!*input) + return -1; /* bitching's done elsewhere */ + return epoch; } int extract_ipv4(char **input, char *what, struct in_addr *addr) { - char *s = *input; - char c; - - while (isdigit(*s) || *s == '.') { - s++; - } - if (s == *input) { - bitch("%s is not valid", what); - return -1; - } - if (*s && !isspace(*s) && *s != ';' && *s != ')') { - bitch("%s is not valid", what); - return -1; - } - c = *s; - *s = 0; - if (inet_pton(AF_INET, *input, addr) != 1) { - *s = c; - bitch("cannot parse %s", what); - return -1; - } - *s = c; - *input = skip_white_space(s); - if (!*input) { - return -1; /* bitching's done elsewhere */ - } - return 1; + char *s = *input; + char c; + + while (isdigit(*s) || *s == '.') { + s++; + } + if (s == *input) { + bitch("%s is not valid", what); + return -1; + } + if (*s && !isspace(*s) && *s != ';' && *s != ')') { + bitch("%s is not valid", what); + return -1; + } + c = *s; + *s = 0; + if (inet_pton(AF_INET, *input, addr) != 1) { + *s = c; + bitch("cannot parse %s", what); + return -1; + } + *s = c; + *input = skip_white_space(s); + if (!*input) { + return -1; /* bitching's done elsewhere */ + } + return 1; } int extract_ipv6(char **input, char *what, struct in6_addr *addr) { - char *s = *input; - char c; - - while (isdigit(*s) || *s == ':' || *s == '.' || - (*s >= 'a' && *s <= 'f') || (*s >= 'A' && *s <= 'F')) - { - s++; - } - if (s == *input) { - bitch("%s is not valid", what); - return -1; - } - if (*s && !isspace(*s) && *s != ';' && *s != ')') { - bitch("%s is not valid", what); - return -1; - } - c = *s; - *s = 0; - if (inet_pton(AF_INET6, *input, addr) != 1) { - *s = c; - bitch("cannot parse %s", what); - return -1; - } - *s = c; - *input = skip_white_space(s); - if (!*input) { - return -1; /* bitching's done elsewhere */ - } - return 1; + char *s = *input; + char c; + + while (isdigit(*s) || *s == ':' || *s == '.' || + (*s >= 'a' && *s <= 'f') || (*s >= 'A' && *s <= 'F')) + { + s++; + } + if (s == *input) { + bitch("%s is not valid", what); + return -1; + } + if (*s && !isspace(*s) && *s != ';' && *s != ')') { + bitch("%s is not valid", what); + return -1; + } + c = *s; + *s = 0; + if (inet_pton(AF_INET6, *input, addr) != 1) { + *s = c; + bitch("cannot parse %s", what); + return -1; + } + *s = c; + *input = skip_white_space(s); + if (!*input) { + return -1; /* bitching's done elsewhere */ + } + return 1; } int extract_u64(char **input, char *what, uint64_t *r) { - char *s = *input; - uint8_t result = 0; - unsigned u; - - #define GETHEXBLOCK if (!isxdigit(*s)) { bitch("%s is not valid", what); return -1; } \ - u = 0; \ - while (isxdigit(*s)) { \ - if (isdigit(*s)) { \ - u = (u << 4) | (*s - '0'); \ - } else if (*s >= 'a' && *s <= 'f') { \ - u = (u << 4) | (*s - 'a' + 10); \ - } else { \ - u = (u << 4) | (*s - 'A' + 10); \ - } \ - s++; \ - } \ - if (u > 0xffff) { bitch("%s is not valid, hex out of range", what); return -1; } \ - result = (result << 16) | u; - #define SKIPCOLON if (*s != ':') { bitch("%s is not valid", what); return -1; } s++; - - GETHEXBLOCK; SKIPCOLON; - GETHEXBLOCK; SKIPCOLON; - GETHEXBLOCK; SKIPCOLON; - GETHEXBLOCK; - *r = result; - - #undef GETHEXBLOCK - #undef SKIPCOLON - - if (*s && !isspace(*s) && *s != ';' && *s != ')') { - bitch("%s is not valid", what); - return -1; - } - *input = skip_white_space(s); - if (!*input) { - return -1; /* bitching's done elsewhere */ - } - return 1; + char *s = *input; + uint8_t result = 0; + unsigned u; + + #define GETHEXBLOCK if (!isxdigit(*s)) { bitch("%s is not valid", what); return -1; } \ + u = 0; \ + while (isxdigit(*s)) { \ + if (isdigit(*s)) { \ + u = (u << 4) | (*s - '0'); \ + } else if (*s >= 'a' && *s <= 'f') { \ + u = (u << 4) | (*s - 'a' + 10); \ + } else { \ + u = (u << 4) | (*s - 'A' + 10); \ + } \ + s++; \ + } \ + if (u > 0xffff) { bitch("%s is not valid, hex out of range", what); return -1; } \ + result = (result << 16) | u; + #define SKIPCOLON if (*s != ':') { bitch("%s is not valid", what); return -1; } s++; + + GETHEXBLOCK; SKIPCOLON; + GETHEXBLOCK; SKIPCOLON; + GETHEXBLOCK; SKIPCOLON; + GETHEXBLOCK; + *r = result; + + #undef GETHEXBLOCK + #undef SKIPCOLON + + if (*s && !isspace(*s) && *s != ';' && *s != ')') { + bitch("%s is not valid", what); + return -1; + } + *input = skip_white_space(s); + if (!*input) { + return -1; /* bitching's done elsewhere */ + } + return 1; } struct binary_data bad_binary_data(void) { - struct binary_data r; - r.length = -1; - r.data = NULL; - return r; + struct binary_data r; + r.length = -1; + r.data = NULL; + return r; } struct binary_data extract_base64_binary_data(char **input, char *what) { - char b64[4096]; - int l64 = 0; - char *s = *input; - struct binary_data r = bad_binary_data(); - int bl; - - while (s && *s) { - if (!isalnum(*s) && *s != '=' && *s != '+' && *s != '/') { - bitch("%s expected", what); - return r; - } - while (isalnum(*s) || *s == '=' || *s == '+' || *s == '/') { - if (l64 >= 4095) { - bitch("%s is too long", what); - return r; - } - b64[l64++] = *s++; - } - s = skip_white_space(s); - } - *input = s; - if (!s) return r; - b64[l64] = 0; - bl = (l64 * 3 + 3)/4; - r.data = getmem(bl); - r.length = decode_base64(r.data, b64, bl); - if (r.length < 0) { - bitch("error decoding base64 %s", what); - return r; - } - return r; + char b64[4096]; + int l64 = 0; + char *s = *input; + struct binary_data r = bad_binary_data(); + int bl; + + while (s && *s) { + if (!isalnum(*s) && *s != '=' && *s != '+' && *s != '/') { + bitch("%s expected", what); + return r; + } + while (isalnum(*s) || *s == '=' || *s == '+' || *s == '/') { + if (l64 >= 4095) { + bitch("%s is too long", what); + return r; + } + b64[l64++] = *s++; + } + s = skip_white_space(s); + } + *input = s; + if (!s) return r; + b64[l64] = 0; + bl = (l64 * 3 + 3)/4; + r.data = getmem(bl); + r.length = decode_base64(r.data, b64, bl); + if (r.length < 0) { + bitch("error decoding base64 %s", what); + return r; + } + return r; } struct binary_data extract_base32hex_binary_data(char **input, char *what) { - char b32[4096]; - int l32 = 0; - char *s = *input; - struct binary_data r = bad_binary_data(); - int bl; - - while ( - (*s >= 'A' && *s <= 'V') || - (*s >= 'a' && *s <= 'v') || - (*s >= '0' && *s <= '9') || - *s == '=') - { - if (l32 >= 4095) { - bitch("%s is too long", what); - return r; - } - b32[l32++] = *s++; - } - if (l32 <= 0) { - bitch("%s expected", what); - return r; - } - - s = skip_white_space(s); - *input = s; - if (!s) return r; - - b32[l32] = 0; - bl = (l32 * 5 + 7)/8; - r.data = getmem(bl); - r.length = decode_base32hex(r.data, b32, bl); - if (r.length < 0) { - bitch("error decoding base32hex %s", what); - return r; - } - return r; + char b32[4096]; + int l32 = 0; + char *s = *input; + struct binary_data r = bad_binary_data(); + int bl; + + while ( + (*s >= 'A' && *s <= 'V') || + (*s >= 'a' && *s <= 'v') || + (*s >= '0' && *s <= '9') || + *s == '=') + { + if (l32 >= 4095) { + bitch("%s is too long", what); + return r; + } + b32[l32++] = *s++; + } + if (l32 <= 0) { + bitch("%s expected", what); + return r; + } + + s = skip_white_space(s); + *input = s; + if (!s) return r; + + b32[l32] = 0; + bl = (l32 * 5 + 7)/8; + r.data = getmem(bl); + r.length = decode_base32hex(r.data, b32, bl); + if (r.length < 0) { + bitch("error decoding base32hex %s", what); + return r; + } + return r; } struct binary_data extract_text(char **input, char *what) { - char *s = *input; - struct binary_data r = bad_binary_data(); - char *o = getmem_temp(65536); - int l = 0; - int c; - - if (*s != '"') { - while (*s && !isspace(*s)) { - o[l++] = *s++; - } - *input = skip_white_space(s); - if (!*input) - return r; /* bitching's done elsewhere */ - - o[l] = 0; - r.data = getmem(l+1); - r.length = l; - memcpy(r.data, o, l+1); - return r; - } - s++; + char *s = *input; + struct binary_data r = bad_binary_data(); + char *o = getmem_temp(65536); + int l = 0; + int c; + + if (*s != '"') { + while (*s && !isspace(*s)) { + o[l++] = *s++; + } + *input = skip_white_space(s); + if (!*input) + return r; /* bitching's done elsewhere */ + + o[l] = 0; + r.data = getmem(l+1); + r.length = l; + memcpy(r.data, o, l+1); + return r; + } + s++; more_text: - while (*s && *s != '"') { - if (*s == '\\') { - s++; - if (*s == 0) { - bitch("bad backslash quoting of %s", what); - return r; - } else if (isdigit(*s)) { - c = 0; - while (isdigit(*s)) { - c = c*10 + *s - '0'; - s++; - } - o[l++] = (unsigned char)c; - } else { - o[l] = *s; - goto new_char; - } - } else { - o[l] = *s; + while (*s && *s != '"') { + if (*s == '\\') { + s++; + if (*s == 0) { + bitch("bad backslash quoting of %s", what); + return r; + } else if (isdigit(*s)) { + c = 0; + while (isdigit(*s)) { + c = c*10 + *s - '0'; + s++; + } + o[l++] = (unsigned char)c; + } else { + o[l] = *s; + goto new_char; + } + } else { + o[l] = *s; new_char: - if (l >= 65534) { - bitch("%s string too long", what); - return r; - } - l++; - s++; - } - } - if (!*s) { - if (read_zone_line()) { - s = file_info->buf; - goto more_text; - } else { - bitch("closing quote not found while parsing %s", what); - return r; - } - } - s++; - *input = skip_white_space(s); - if (!*input) - return r; /* bitching's done elsewhere */ - - o[l] = 0; - r.data = getmem(l+1); - r.length = l; - memcpy(r.data, o, l+1); - return r; + if (l >= 65534) { + bitch("%s string too long", what); + return r; + } + l++; + s++; + } + } + if (!*s) { + if (read_zone_line()) { + s = file_info->buf; + goto more_text; + } else { + bitch("closing quote not found while parsing %s", what); + return r; + } + } + s++; + *input = skip_white_space(s); + if (!*input) + return r; /* bitching's done elsewhere */ + + o[l] = 0; + r.data = getmem(l+1); + r.length = l; + memcpy(r.data, o, l+1); + return r; } struct binary_data extract_hex_binary_data(char **input, char *what, int eat_whitespace) { - char hex[4096]; - char *s = *input; - struct binary_data r = bad_binary_data(); - int hl, hi, hb; - - hex[0] = '0'; - hl = 1; - - if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) - s += 2; - if (eat_whitespace == EXTRACT_DONT_EAT_WHITESPACE) { - while (isxdigit(*s)) { - if (hl >= 4095) { - bitch("%s is too long", what); - return r; - } - hex[hl] = *s; - s++; - hl++; - } - if (*s && !isspace(*s) && *s != ';' && *s != ')') { - bitch("%s is not valid", what); - return r; - } - *input = skip_white_space(s); - } else if (eat_whitespace == EXTRACT_EAT_WHITESPACE) { - while (s && *s) { - if (!isxdigit(*s)) { - bitch("%s expected", what); - return r; - } - while (isxdigit(*s)) { - if (hl >= 4095) { - bitch("%s is too long", what); - return r; - } - hex[hl++] = *s++; - } - s = skip_white_space(s); - } - *input = s; - } else { - bitch("%s: internal: invalid eat_whitespace", what); - } - - if (!*input) - return r; /* bitching's done elsewhere */ - - hb = hl % 2 ? 1 : 0; - if (hb == 0) - bitch("%s: hex data does not represent whole number of bytes", what); - r.data = getmem(hl/2); - r.length = hl/2; - memset(r.data, 0, r.length); - for (hi = 0; hi < hl-hb; hi++) { - r.data[hi/2] <<= 4; - r.data[hi/2] |= 0x0f & (isdigit(hex[hi+hb]) ? hex[hi+hb] - '0' : tolower(hex[hi+hb]) - 'a' + 10); - } - return r; + char hex[4096]; + char *s = *input; + struct binary_data r = bad_binary_data(); + int hl, hi, hb; + + hex[0] = '0'; + hl = 1; + + if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) + s += 2; + if (eat_whitespace == EXTRACT_DONT_EAT_WHITESPACE) { + while (isxdigit(*s)) { + if (hl >= 4095) { + bitch("%s is too long", what); + return r; + } + hex[hl] = *s; + s++; + hl++; + } + if (*s && !isspace(*s) && *s != ';' && *s != ')') { + bitch("%s is not valid", what); + return r; + } + *input = skip_white_space(s); + } else if (eat_whitespace == EXTRACT_EAT_WHITESPACE) { + while (s && *s) { + if (!isxdigit(*s)) { + bitch("%s expected", what); + return r; + } + while (isxdigit(*s)) { + if (hl >= 4095) { + bitch("%s is too long", what); + return r; + } + hex[hl++] = *s++; + } + s = skip_white_space(s); + } + *input = s; + } else { + bitch("%s: internal: invalid eat_whitespace", what); + } + + if (!*input) + return r; /* bitching's done elsewhere */ + + hb = hl % 2 ? 1 : 0; + if (hb == 0) + bitch("%s: hex data does not represent whole number of bytes", what); + r.data = getmem(hl/2); + r.length = hl/2; + memset(r.data, 0, r.length); + for (hi = 0; hi < hl-hb; hi++) { + r.data[hi/2] <<= 4; + r.data[hi/2] |= 0x0f & (isdigit(hex[hi+hb]) ? hex[hi+hb] - '0' : tolower(hex[hi+hb]) - 'a' + 10); + } + return r; } struct binary_data new_set(void) { - struct binary_data set; - set.length = 256*(1+1+32); - set.data = getmem_temp(set.length); - memset(set.data, 0, set.length); - return set; + struct binary_data set; + set.length = 256*(1+1+32); + set.data = getmem_temp(set.length); + memset(set.data, 0, set.length); + return set; } void add_bit_to_set(struct binary_data *set, int bit) { - int map; - int map_base; - int byte; - - if (bit < 0 || bit > 65535) - croakx(1, "bitmap index out of range"); - map = bit / 256; - map_base = map*(1+1+32); - set->data[map_base] = map; - bit = bit & 0xff; - byte = bit / 8; - if (set->data[map_base + 1] <= byte) - set->data[map_base + 1] = byte+1; - set->data[map_base + 2 + byte] |= 0x80 >> (bit & 0x07); + int map; + int map_base; + int byte; + + if (bit < 0 || bit > 65535) + croakx(1, "bitmap index out of range"); + map = bit / 256; + map_base = map*(1+1+32); + set->data[map_base] = map; + bit = bit & 0xff; + byte = bit / 8; + if (set->data[map_base + 1] <= byte) + set->data[map_base + 1] = byte+1; + set->data[map_base + 2 + byte] |= 0x80 >> (bit & 0x07); } struct binary_data compressed_set(struct binary_data *set) { - int len = 0; - int map; - int map_base; - struct binary_data r; - - for (map = 0; map <= 255; map++) { - map_base = map*(1+1+32); - if (set->data[map_base+1]) { - len += 2 + set->data[map_base+1]; - } - } - r.length = len; - r.data = getmem(r.length); - len = 0; - for (map = 0; map <= 255; map++) { - map_base = map*(1+1+32); - if (set->data[map_base+1]) { - memcpy(&r.data[len], &set->data[map_base], 2 + set->data[map_base+1]); - len += 2 + set->data[map_base+1]; - } - } - return r; + int len = 0; + int map; + int map_base; + struct binary_data r; + + for (map = 0; map <= 255; map++) { + map_base = map*(1+1+32); + if (set->data[map_base+1]) { + len += 2 + set->data[map_base+1]; + } + } + r.length = len; + r.data = getmem(r.length); + len = 0; + for (map = 0; map <= 255; map++) { + map_base = map*(1+1+32); + if (set->data[map_base+1]) { + memcpy(&r.data[len], &set->data[map_base], 2 + set->data[map_base+1]); + len += 2 + set->data[map_base+1]; + } + } + return r; } struct binary_data compose_binary_data(const char *fmt, int tmp, ...) { - va_list ap; - const char *args; - int sz; - struct binary_data bd; - struct binary_data r; - char *t; - uint8_t b1; - uint16_t b2; - uint32_t b4; - uint64_t b8; - - va_start(ap, tmp); - args = fmt; - sz = 0; - while (*args) { - switch (*args++) { - case '1': - va_arg(ap, unsigned int); - sz += 1; - break; - case '2': - va_arg(ap, unsigned int); - sz += 2; - break; - case '4': - va_arg(ap, unsigned int); - sz += 4; - break; - case '8': - va_arg(ap, uint64_t); - sz += 8; - break; - case 'd': - bd = va_arg(ap, struct binary_data); - sz += bd.length; - break; - case 'b': - bd = va_arg(ap, struct binary_data); - if (bd.length > 255) - croak(5, "compose_binary_data: 'b' data too long"); - sz += bd.length + 1; - break; - case 'B': - bd = va_arg(ap, struct binary_data); - if (bd.length > 65535) - croak(5, "compose_binary_data: 'B' data too long"); - sz += bd.length + 2; - break; - default: - croak(5, "compose_binary_data: bad format"); - } - } - va_end(ap); - - r.length = sz; - r.data = tmp ? getmem_temp(sz) : getmem(sz); - t = r.data; - va_start(ap, tmp); - args = fmt; - while (*args) { - switch (*args++) { - case '1': - b1 = (uint8_t)va_arg(ap, unsigned int); - memcpy(t, &b1, 1); - t += 1; - break; - case '2': - b2 = htons(va_arg(ap, unsigned int)); - memcpy(t, &b2, 2); - t += 2; - break; - case '4': - b4 = htonl(va_arg(ap, unsigned int)); - memcpy(t, &b4, 4); - t += 4; - break; - case '8': - b8 = htonl(va_arg(ap, uint64_t)); - memcpy(t, &b8, 8); - t += 8; - break; - case 'd': - bd = va_arg(ap, struct binary_data); - memcpy(t, bd.data, bd.length); - t += bd.length; - break; - case 'b': - bd = va_arg(ap, struct binary_data); - b1 = (uint8_t)bd.length; - memcpy(t, &b1, 1); - t += 1; - memcpy(t, bd.data, bd.length); - t += bd.length; - break; - case 'B': - bd = va_arg(ap, struct binary_data); - b2 = htons(bd.length); - memcpy(t, &b2, 2); - t += 2; - memcpy(t, bd.data, bd.length); - t += bd.length; - break; - default: - croak(5, "compose_binary_data: bad format"); - } - } - va_end(ap); - return r; + va_list ap; + const char *args; + int sz; + struct binary_data bd; + struct binary_data r; + char *t; + uint8_t b1; + uint16_t b2; + uint32_t b4; + uint64_t b8; + + va_start(ap, tmp); + args = fmt; + sz = 0; + while (*args) { + switch (*args++) { + case '1': + va_arg(ap, unsigned int); + sz += 1; + break; + case '2': + va_arg(ap, unsigned int); + sz += 2; + break; + case '4': + va_arg(ap, unsigned int); + sz += 4; + break; + case '8': + va_arg(ap, uint64_t); + sz += 8; + break; + case 'd': + bd = va_arg(ap, struct binary_data); + sz += bd.length; + break; + case 'b': + bd = va_arg(ap, struct binary_data); + if (bd.length > 255) + croak(5, "compose_binary_data: 'b' data too long"); + sz += bd.length + 1; + break; + case 'B': + bd = va_arg(ap, struct binary_data); + if (bd.length > 65535) + croak(5, "compose_binary_data: 'B' data too long"); + sz += bd.length + 2; + break; + default: + croak(5, "compose_binary_data: bad format"); + } + } + va_end(ap); + + r.length = sz; + r.data = tmp ? getmem_temp(sz) : getmem(sz); + t = r.data; + va_start(ap, tmp); + args = fmt; + while (*args) { + switch (*args++) { + case '1': + b1 = (uint8_t)va_arg(ap, unsigned int); + memcpy(t, &b1, 1); + t += 1; + break; + case '2': + b2 = htons(va_arg(ap, unsigned int)); + memcpy(t, &b2, 2); + t += 2; + break; + case '4': + b4 = htonl(va_arg(ap, unsigned int)); + memcpy(t, &b4, 4); + t += 4; + break; + case '8': + b8 = htonl(va_arg(ap, uint64_t)); + memcpy(t, &b8, 8); + t += 8; + break; + case 'd': + bd = va_arg(ap, struct binary_data); + memcpy(t, bd.data, bd.length); + t += bd.length; + break; + case 'b': + bd = va_arg(ap, struct binary_data); + b1 = (uint8_t)bd.length; + memcpy(t, &b1, 1); + t += 1; + memcpy(t, bd.data, bd.length); + t += bd.length; + break; + case 'B': + bd = va_arg(ap, struct binary_data); + b2 = htons(bd.length); + memcpy(t, &b2, 2); + t += 2; + memcpy(t, bd.data, bd.length); + t += bd.length; + break; + default: + croak(5, "compose_binary_data: bad format"); + } + } + va_end(ap); + return r; } /* implementation taken from FreeBSD's libc (minus the __restrict keyword) */ char * mystpcpy(char *to, const char *from) { - for (; (*to = *from); ++from, ++to); - return(to); + for (; (*to = *from); ++from, ++to); + return(to); } size_t mystrlcat(char *dst, const char *src, size_t siz) { - char *d = dst; - const char *s = src; - size_t n = siz; - size_t dlen; - - /* Find the end of dst and adjust bytes left but don't go past end */ - while (n-- != 0 && *d != '\0') - d++; - dlen = d - dst; - n = siz - dlen; - - if (n == 0) - return(dlen + strlen(s)); - while (*s != '\0') { - if (n != 1) { - *d++ = *s; - n--; - } - s++; - } - *d = '\0'; - - return(dlen + (s - src)); /* count does not include NUL */ + char *d = dst; + const char *s = src; + size_t n = siz; + size_t dlen; + + /* Find the end of dst and adjust bytes left but don't go past end */ + while (n-- != 0 && *d != '\0') + d++; + dlen = d - dst; + n = siz - dlen; + + if (n == 0) + return(dlen + strlen(s)); + while (*s != '\0') { + if (n != 1) { + *d++ = *s; + n--; + } + s++; + } + *d = '\0'; + + return(dlen + (s - src)); /* count does not include NUL */ } diff --git a/textparse.h b/textparse.h index 2556129..6e8ba67 100644 --- a/textparse.h +++ b/textparse.h @@ -12,8 +12,8 @@ #include struct binary_data { - int length; - char *data; + int length; + char *data; }; struct binary_data compose_binary_data(const char *fmt, int tmp, ...); diff --git a/threads.c b/threads.c index d78ca15..9080e47 100644 --- a/threads.c +++ b/threads.c @@ -7,10 +7,10 @@ #include #endif -/* supposedly, - #if defined(PTW32_VERSION) || defined(__hpux) - return pthread_num_processors_np(); - but I cannot verify that at the moment +/* supposedly, + #if defined(PTW32_VERSION) || defined(__hpux) + return pthread_num_processors_np(); + but I cannot verify that at the moment */ #if defined(__GLIBC__) @@ -18,16 +18,16 @@ int ncpus(void) { return get_nprocs(); } #elif defined(__APPLE__) || defined(__FreeBSD__) int ncpus(void) { - int count; - size_t size=sizeof(count); - return sysctlbyname("hw.ncpu",&count,&size,NULL,0) ? 0 : count; + int count; + size_t size=sizeof(count); + return sysctlbyname("hw.ncpu",&count,&size,NULL,0) ? 0 : count; } #else int ncpus(void) { return 0; } /* "Don't know */ #endif -/* Supposedly, sysconf() can also be used in some cases: - #include - int const count=sysconf(_SC_NPROCESSORS_ONLN); - return (count>0)?count:0; +/* Supposedly, sysconf() can also be used in some cases: + #include + int const count=sysconf(_SC_NPROCESSORS_ONLN); + return (count>0)?count:0; */ diff --git a/tlsa.c b/tlsa.c index 5cbd3c7..b3e64ec 100644 --- a/tlsa.c +++ b/tlsa.c @@ -25,97 +25,97 @@ static struct rr* tlsa_parse(char *name, long ttl, int type, char *s) { - struct rr_tlsa *rr = getmem(sizeof(*rr)); - int cert_usage, selector, matching_type; - - cert_usage = extract_integer(&s, "certificate usage field", NULL); - if (cert_usage < 0) return NULL; - if (cert_usage > 3) - return bitch("bad certificate usage field"); - rr->cert_usage = cert_usage; - - selector = extract_integer(&s, "selector field", NULL); - if (selector < 0) return NULL; - if (selector > 1) - return bitch("bad selector field"); - rr->selector = selector; - - matching_type = extract_integer(&s, "matching type field", NULL); - if (matching_type < 0) return NULL; - if (matching_type > 2) - return bitch("bad matching type field"); - rr->matching_type = matching_type; - - rr->association_data = extract_hex_binary_data(&s, "certificate association data", EXTRACT_EAT_WHITESPACE); - if (rr->association_data.length < 0) return NULL; - switch (rr->matching_type) { - case 1: - if (rr->association_data.length != SHA256_BYTES) - return bitch("bad SHA-256 hash length"); - break; - case 2: - if (rr->association_data.length != SHA512_BYTES) - return bitch("bad SHA-512 hash length"); - break; - } - - if (*s) { - return bitch("garbage after valid TLSA data"); - } - return store_record(type, name, ttl, rr); + struct rr_tlsa *rr = getmem(sizeof(*rr)); + int cert_usage, selector, matching_type; + + cert_usage = extract_integer(&s, "certificate usage field", NULL); + if (cert_usage < 0) return NULL; + if (cert_usage > 3) + return bitch("bad certificate usage field"); + rr->cert_usage = cert_usage; + + selector = extract_integer(&s, "selector field", NULL); + if (selector < 0) return NULL; + if (selector > 1) + return bitch("bad selector field"); + rr->selector = selector; + + matching_type = extract_integer(&s, "matching type field", NULL); + if (matching_type < 0) return NULL; + if (matching_type > 2) + return bitch("bad matching type field"); + rr->matching_type = matching_type; + + rr->association_data = extract_hex_binary_data(&s, "certificate association data", EXTRACT_EAT_WHITESPACE); + if (rr->association_data.length < 0) return NULL; + switch (rr->matching_type) { + case 1: + if (rr->association_data.length != SHA256_BYTES) + return bitch("bad SHA-256 hash length"); + break; + case 2: + if (rr->association_data.length != SHA512_BYTES) + return bitch("bad SHA-512 hash length"); + break; + } + + if (*s) { + return bitch("garbage after valid TLSA data"); + } + return store_record(type, name, ttl, rr); } static char* tlsa_human(struct rr *rrv) { - RRCAST(tlsa); + RRCAST(tlsa); char s[1024]; snprintf(s, 1024, "%d %d %d ...", - rr->cert_usage, rr->selector, rr->matching_type); + rr->cert_usage, rr->selector, rr->matching_type); return quickstrdup_temp(s); } static struct binary_data tlsa_wirerdata(struct rr *rrv) { - RRCAST(tlsa); + RRCAST(tlsa); - return compose_binary_data("111d", 1, - rr->cert_usage, rr->selector, rr->matching_type, - rr->association_data); + return compose_binary_data("111d", 1, + rr->cert_usage, rr->selector, rr->matching_type, + rr->association_data); } static void* tlsa_validate_set(struct rr_set *rr_set) { - struct rr *rr; - struct named_rr *named_rr; - char *s; - int port = 0; - int len; - - if (G.opt.policy_checks[POLICY_TLSA_HOST]) { - rr = rr_set->tail; - named_rr = rr_set->named_rr; - - /* _25._tcp.mail.example.com. */ - s = named_rr->name; - if (*s != '_') { + struct rr *rr; + struct named_rr *named_rr; + char *s; + int port = 0; + int len; + + if (G.opt.policy_checks[POLICY_TLSA_HOST]) { + rr = rr_set->tail; + named_rr = rr_set->named_rr; + + /* _25._tcp.mail.example.com. */ + s = named_rr->name; + if (*s != '_') { not_a_prefixed_domain_name: - return moan(rr->file_name, rr->line, "not a proper prefixed DNS domain name"); - } - s++; - while (isdigit(*s)) { - port = port * 10 + *s - '0'; - s++; - } - if (port <= 0 || port > 65535) goto not_a_prefixed_domain_name; - if (*s++ != '.') goto not_a_prefixed_domain_name; - len = strlen(s); - if (len < 6) goto not_a_prefixed_domain_name; - if (memcmp(s, "_tcp.", 5) != 0 && - memcmp(s, "_udp.", 5) != 0 && - memcmp(s, "_sctp.", 6) != 0) goto not_a_prefixed_domain_name; - } - return NULL; + return moan(rr->file_name, rr->line, "not a proper prefixed DNS domain name"); + } + s++; + while (isdigit(*s)) { + port = port * 10 + *s - '0'; + s++; + } + if (port <= 0 || port > 65535) goto not_a_prefixed_domain_name; + if (*s++ != '.') goto not_a_prefixed_domain_name; + len = strlen(s); + if (len < 6) goto not_a_prefixed_domain_name; + if (memcmp(s, "_tcp.", 5) != 0 && + memcmp(s, "_udp.", 5) != 0 && + memcmp(s, "_sctp.", 6) != 0) goto not_a_prefixed_domain_name; + } + return NULL; } struct rr_methods tlsa_methods = { tlsa_parse, tlsa_human, tlsa_wirerdata, tlsa_validate_set, NULL }; diff --git a/txt.c b/txt.c index ee4ea09..f0cd423 100644 --- a/txt.c +++ b/txt.c @@ -22,72 +22,72 @@ static struct rr *txt_parse(char *name, long ttl, int type, char *s) { - struct rr_txt *rr; - struct binary_data txt; - struct rr_txt_segment *first = NULL; - struct rr_txt_segment *last = NULL; - struct rr_txt_segment *cur = NULL; - int i; + struct rr_txt *rr; + struct binary_data txt; + struct rr_txt_segment *first = NULL; + struct rr_txt_segment *last = NULL; + struct rr_txt_segment *cur = NULL; + int i; - i = 0; - while (*s) { - freeall_temp(); - txt = extract_text(&s, "text segment"); - if (txt.length < 0) - return NULL; - if (txt.length > 255) - return bitch("TXT segment too long"); - i++; - cur = getmem(sizeof(*cur)); - cur->txt = txt; - cur->next = NULL; - if (!first) - first = cur; - if (last) - last->next = cur; - last = cur; - } - if (i == 0) - return bitch("empty text record"); + i = 0; + while (*s) { + freeall_temp(); + txt = extract_text(&s, "text segment"); + if (txt.length < 0) + return NULL; + if (txt.length > 255) + return bitch("TXT segment too long"); + i++; + cur = getmem(sizeof(*cur)); + cur->txt = txt; + cur->next = NULL; + if (!first) + first = cur; + if (last) + last->next = cur; + last = cur; + } + if (i == 0) + return bitch("empty text record"); - rr = getmem(sizeof(*rr)); - rr->count = i; - rr->txt = first; + rr = getmem(sizeof(*rr)); + rr->count = i; + rr->txt = first; - return store_record(type, name, ttl, rr); + return store_record(type, name, ttl, rr); } static char* txt_human(struct rr *rrv) { - RRCAST(txt); + RRCAST(txt); char ss[1024]; - char *s = ss; - int l; - struct rr_txt_segment *seg = rr->txt; + char *s = ss; + int l; + struct rr_txt_segment *seg = rr->txt; - while (seg) { - /* XXX would be nice to escape " with \ in strings */ - l = snprintf(s, 1024-(s-ss), "\"%s\" ", seg->txt.data); - s += l; - seg = seg->next; - } + while (seg) { + /* XXX would be nice to escape " with \ in strings */ + l = snprintf(s, 1024-(s-ss), "\"%s\" ", seg->txt.data); + s += l; + seg = seg->next; + } return quickstrdup_temp(ss); } static struct binary_data txt_wirerdata(struct rr *rrv) { - RRCAST(txt); - struct binary_data r, t; - struct rr_txt_segment *seg = rr->txt; + RRCAST(txt); + struct binary_data r, t; + struct rr_txt_segment *seg = rr->txt; - r = bad_binary_data(); - t.length = 0; - t.data = NULL; - while (seg) { - r = compose_binary_data("db", 1, t, seg->txt); - t = r; - seg = seg->next; - } + r = bad_binary_data(); + t.length = 0; + t.data = NULL; + while (seg) { + r = compose_binary_data("db", 1, t, seg->txt); + t = r; + seg = seg->next; + } return r; } diff --git a/x25.c b/x25.c index 240534f..a86efca 100644 --- a/x25.c +++ b/x25.c @@ -23,40 +23,40 @@ static struct rr *x25_parse(char *name, long ttl, int type, char *s) { - struct rr_x25 *rr = getmem(sizeof(*rr)); - int i; - - rr->psdn_address = extract_text(&s, "PSDN-address"); - if (rr->psdn_address.length < 0) - return NULL; - if (rr->psdn_address.length > 255) - return bitch("PSDN-address too long"); - if (rr->psdn_address.length < 4) - return bitch("PSDN-address too short"); - for (i = 0; i < rr->psdn_address.length; i++) { - if (!isdigit(rr->psdn_address.data[i])) - return bitch("PSDN-address contains non-digits"); - } - - if (*s) { - return bitch("garbage after valid X25 data"); - } - - return store_record(type, name, ttl, rr); + struct rr_x25 *rr = getmem(sizeof(*rr)); + int i; + + rr->psdn_address = extract_text(&s, "PSDN-address"); + if (rr->psdn_address.length < 0) + return NULL; + if (rr->psdn_address.length > 255) + return bitch("PSDN-address too long"); + if (rr->psdn_address.length < 4) + return bitch("PSDN-address too short"); + for (i = 0; i < rr->psdn_address.length; i++) { + if (!isdigit(rr->psdn_address.data[i])) + return bitch("PSDN-address contains non-digits"); + } + + if (*s) { + return bitch("garbage after valid X25 data"); + } + + return store_record(type, name, ttl, rr); } static char* x25_human(struct rr *rrv) { - RRCAST(x25); + RRCAST(x25); return rr->psdn_address.data; } static struct binary_data x25_wirerdata(struct rr *rrv) { - RRCAST(x25); + RRCAST(x25); - return compose_binary_data("b", 1, rr->psdn_address); + return compose_binary_data("b", 1, rr->psdn_address); } struct rr_methods x25_methods = { x25_parse, x25_human, x25_wirerdata, NULL, NULL };