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; 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; 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; 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); }
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"); 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"); 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 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"); if (flags < 0) return NULL; if (flags & 0xfefe) 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"); 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; }