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