Refactor to use new VerifyAlg context, and start implementing logic for querying DNSKEYs.

This commit is contained in:
Giovanni Bajo
2012-04-25 17:46:53 +02:00
committed by Simon Kelley
parent 366dfcb907
commit adca3e9c4b

View File

@@ -94,9 +94,17 @@ static int rrset_canonical_order(const void *r1, const void *r2)
return res; return res;
} }
static int validate_rrsig(struct dns_header *header, size_t pktlen, typedef struct PendingRRSIGValidation
{
VerifyAlgCtx *alg;
char *signer_name;
int keytag;
} PendingRRSIGValidation;
static int begin_rrsig_validation(struct dns_header *header, size_t pktlen,
unsigned char *reply, int count, char *owner, unsigned char *reply, int count, char *owner,
int sigclass, int sigrdlen, unsigned char *sig) int sigclass, int sigrdlen, unsigned char *sig,
PendingRRSIGValidation *out)
{ {
int i, res; int i, res;
int sigtype, sigalg, siglbl; int sigtype, sigalg, siglbl;
@@ -119,7 +127,7 @@ static int validate_rrsig(struct dns_header *header, size_t pktlen,
GETSHORT(keytag, sig); GETSHORT(keytag, sig);
sigrdlen -= 18; sigrdlen -= 18;
if (sigalg >= countof(valgs) || !valgs[sigalg].set_signature) if (!verifyalg_supported(sigalg))
{ {
printf("RRSIG algorithm not supported: %d\n", sigalg); printf("RRSIG algorithm not supported: %d\n", sigalg);
return 0; return 0;
@@ -165,42 +173,79 @@ static int validate_rrsig(struct dns_header *header, size_t pktlen,
/* Now initialize the signature verification algorithm and process the whole /* Now initialize the signature verification algorithm and process the whole
RRset */ RRset */
const VerifyAlg *alg = &valgs[sigalg]; VerifyAlgCtx *alg = verifyalg_alloc(sigalg);
if (!alg->set_signature(sig, sigrdlen)) if (!alg)
return 0;
if (!alg->vtbl->set_signature(alg, sig, sigrdlen))
return 0; return 0;
alg->begin_data(); alg->vtbl->begin_data(alg);
alg->add_data(sigrdata, 18); alg->vtbl->add_data(alg, sigrdata, 18);
alg->add_data(signer_name, strlen(signer_name)-1); /* remove trailing dot */ alg->vtbl->add_data(alg, signer_name, strlen(signer_name)-1); /* remove trailing dot */
for (i = 0; i < rrsetidx; ++i) for (i = 0; i < rrsetidx; ++i)
{ {
int rdlen; int rdlen;
alg->add_data(owner, strlen(owner)); alg->vtbl->add_data(alg, owner, strlen(owner));
alg->add_data(&sigtype, 2); alg->vtbl->add_data(alg, &sigtype, 2);
alg->add_data(&sigclass, 2); alg->vtbl->add_data(alg, &sigclass, 2);
alg->add_data(&sigttl, 4); alg->vtbl->add_data(alg, &sigttl, 4);
p = (unsigned char*)(rrset[i]); p = (unsigned char*)(rrset[i]);
p += 8; p += 8;
GETSHORT(rdlen, p); GETSHORT(rdlen, p);
/* TODO: instead of a direct add_data(), we must call a RRtype-specific /* TODO: instead of a direct add_data(), we must call a RRtype-specific
function, that extract and canonicalizes domain names within RDATA. */ function, that extract and canonicalizes domain names within RDATA. */
alg->add_data(p-2, rdlen+2); alg->vtbl->add_data(alg, p-2, rdlen+2);
} }
alg->end_data(); alg->vtbl->end_data(alg);
/* TODO: now we need to fetch the DNSKEY of signer_name with the specified out->alg = alg;
keytag, and check whether it validates with the current algorithm. */ out->keytag = keytag;
/* out->signer_name = signer_name;
pseudo-code: return 1;
}
char *key; int keylen; static int end_rrsig_validation(PendingRRSIGValidation *val, struct crec *crec_dnskey)
if (!fetch_dnskey(signer_name, keytag, &key, &keylen)) {
return 0;
return alg->verify(key, keylen); }
*/
return 0; static void dnssec_parserrsig(struct dns_header *header, size_t pktlen,
unsigned char *reply, int count, char *owner,
int sigclass, int sigrdlen, unsigned char *sig)
{
PendingRRSIGValidation val;
/* Initiate the RRSIG validation process. The pending state is returned into val. */
if (!begin_rrsig_validation(header, pktlen, reply, count, owner, sigclass, sigrdlen, sig, &val))
return;
printf("RRSIG: querying cache for DNSKEY %s (keytag: %d)\n", val.signer_name, val.keytag);
/* Look in the cache for all the DNSKEYs with matching signer_name and keytag */
char onekey = 0;
struct crec *crecp = NULL;
while (crecp = cache_find_by_name(crecp, val.signer_name, time(0), F_DNSKEY)) /* TODO: time(0) */
{
onekey = 1;
if (crecp->addr.key.keytag != val.keytag)
continue;
printf("RRSIG: found DNSKEY %d in cache, attempting validation\n", val.keytag);
if (end_rrsig_validation(&val, crecp))
printf("Validation OK\n");
else
printf("Validation FAILED\n");
}
if (!onekey)
{
printf("DNSKEY not found, need to fetch it");
/* TODO: store PendingRRSIGValidation in routing table,
fetch key (and make it go through dnssec_parskey), then complete validation. */
}
} }
@@ -231,7 +276,7 @@ int dnssec_validate(struct dns_header *header, size_t pktlen)
There is a memory vs CPU conflict here; should we validate everything There is a memory vs CPU conflict here; should we validate everything
to save memory and thus waste CPU, or better first acquire all information to save memory and thus waste CPU, or better first acquire all information
(wasting memory) and then doing the minimum CPU computations required? */ (wasting memory) and then doing the minimum CPU computations required? */
validate_rrsig(header, pktlen, reply, ntohs(header->ancount), owner, qclass, rdlen, p); dnssec_parserrsig(header, pktlen, reply, ntohs(header->ancount), owner, qclass, rdlen, p);
} }
p += rdlen; p += rdlen;
} }