Start parsing DNSKEY records and insert them into cache.
diff --git a/src/dnssec.c b/src/dnssec.c
index 1784301..ccafeff 100644
--- a/src/dnssec.c
+++ b/src/dnssec.c
@@ -269,6 +269,87 @@
}
}
+/* Compute keytag (checksum to quickly index a key). See RFC4034 */
+static int dnskey_keytag(unsigned char *rdata, int rdlen)
+{
+ unsigned long ac;
+ int i;
+
+ ac = 0;
+ for (i = 0; i < rdlen; ++i)
+ ac += (i & 1) ? rdata[i] : rdata[i] << 8;
+ ac += (ac >> 16) & 0xFFFF;
+ return ac & 0xFFFF;
+}
+
+int dnssec_parsekey(struct dns_header *header, size_t pktlen, char *owner, unsigned long ttl,
+ int rdlen, unsigned char *rdata)
+{
+ int flags, proto, alg;
+ struct keydata *key; struct crec *crecp;
+ int explen, keytag;
+ unsigned long exp;
+ unsigned char *ordata = rdata; int ordlen = rdlen;
+
+ CHECKED_GETSHORT(flags, rdata, rdlen);
+ CHECKED_GETCHAR(proto, rdata, rdlen);
+ CHECKED_GETCHAR(alg, rdata, rdlen);
+
+ if (proto != 3)
+ return 0;
+
+ switch (alg)
+ {
+ case 5: /* RSASHA1 */
+ CHECKED_GETCHAR(explen, rdata, rdlen);
+ if (explen == 0)
+ {
+ printf("DNSKEY: RSASHA1: Unsupported huge exponents\n");
+ return 0;
+ }
+
+ if (rdlen < explen)
+ return 0;
+ printf("Alloc'ing: %d bytes\n", rdlen);
+ key = keydata_alloc(rdata, rdlen);
+ printf("Done\n");
+ break;
+
+ default:
+ printf("DNSKEY: Unsupported algorithm: %d\n", alg);
+ return 0;
+ }
+
+ cache_start_insert();
+ /* TODO: time(0) is correct here? */
+ crecp = cache_insert(owner, NULL, time(0), ttl, F_FORWARD | F_DNSKEY);
+ if (crecp)
+ {
+ /* TODO: improve union not to name "uid" this field */
+ crecp->uid = rdlen;
+ crecp->addr.key.keydata = key;
+ crecp->addr.key.algo = alg;
+ crecp->addr.key.keytag = dnskey_keytag(ordata, ordlen);
+ printf("DNSKEY: storing key for %s (keytag: %d)\n", owner, crecp->addr.key.keytag);
+ }
+ else
+ {
+ keydata_free(key);
+ /* TODO: if insertion really might fail, verify we don't depend on cache
+ insertion success for validation workflow correctness */
+ printf("DNSKEY: cache insertion failure\n");
+ return 0;
+ }
+ cache_end_insert();
+ printf("DNSKEY record inserted\n");
+ return 1;
+}
+
+int dnssec_parseds(struct dns_header *header, size_t pktlen, char *owner, unsigned long ttl,
+ int rdlen, unsigned char *rdata)
+{
+ return 0;
+}
int dnssec_validate(struct dns_header *header, size_t pktlen)
{
@@ -289,7 +370,17 @@
GETSHORT(qclass, p);
GETLONG(ttl, p);
GETSHORT(rdlen, p);
- if (qtype == T_RRSIG)
+ if (qtype == T_DS)
+ {
+ printf("DS found\n");
+ dnssec_parseds(header, pktlen, owner, ttl, rdlen, p);
+ }
+ else if (qtype == T_DNSKEY)
+ {
+ printf("DNSKEY found\n");
+ dnssec_parsekey(header, pktlen, owner, qclass, rdlen, p);
+ }
+ else if (qtype == T_RRSIG)
{
printf("RRSIG found\n");
/* TODO: missing logic. We should only validate RRSIGs for which we