]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
lib/dnssec: added missing functions, new key APIs
authorMarek Vavruša <marek.vavrusa@nic.cz>
Fri, 25 Sep 2015 08:40:52 +0000 (10:40 +0200)
committerMarek Vavruša <marek.vavrusa@nic.cz>
Fri, 25 Sep 2015 08:41:32 +0000 (10:41 +0200)
lib/dnssec.c
lib/dnssec.h

index 1dade8f9a3890b09527a7f71aa1bdc56ce2a28b2..b3b576593e57d364d975f6415c0e20a793a4ca9f 100644 (file)
@@ -178,7 +178,8 @@ int kr_rrset_validate_with_key(const knot_pkt_t *pkt, knot_section_t section_id,
        int trim_labels;
        if (key == NULL) {
                const knot_rdata_t *krr = knot_rdataset_at(&keys->rrs, key_pos);
-               ret = kr_dnssec_key_from_rdata(&created_key, krr, keys->owner);
+               ret = kr_dnssec_key_from_rdata(&created_key, keys->owner,
+                                              knot_rdata_data(krr), knot_rdata_rdlen(krr));
                if (ret != 0) {
                        return ret;
                }
@@ -243,12 +244,7 @@ int kr_dnskeys_trusted(const knot_pkt_t *pkt, knot_section_t section_id, const k
        /* RFC4035 5.2, bullet 1
         * The supplied DS record has been authenticated.
         * It has been validated or is part of a configured trust anchor.
-        *
-        * This implementation actually ignores the SEP flag.
         */
-
-#warning TODO: there should be an error saying that there is no matching key
-       int ret = kr_error(KNOT_DNSSEC_ENOKEY);
        for (uint16_t i = 0; i < keys->rrs.rr_count; ++i) {
                /* RFC4035 5.3.1, bullet 8 */ /* ZSK */
                const knot_rdata_t *krr = knot_rdataset_at(&keys->rrs, i);
@@ -258,7 +254,7 @@ int kr_dnskeys_trusted(const knot_pkt_t *pkt, knot_section_t section_id, const k
                }
                
                struct dseckey *key;
-               if (kr_dnssec_key_from_rdata(&key, krr, keys->owner) != 0) {
+               if (kr_dnssec_key_from_rdata(&key, keys->owner, key_data, knot_rdata_rdlen(krr)) != 0) {
                        continue;
                }
                if (kr_authenticate_referral(ta, (dnssec_key_t *) key) != 0) {
@@ -270,42 +266,71 @@ int kr_dnskeys_trusted(const knot_pkt_t *pkt, knot_section_t section_id, const k
                        continue;
                }
                kr_dnssec_key_free(&key);
-               ret = kr_ok();
-               break;
+               return kr_ok();
        }
+       /* No useable key found */
+       return kr_error(ENOENT);
+}
 
-       return ret;
+bool kr_dnssec_key_ksk(const uint8_t *dnskey_rdata)
+{
+       return wire_read_u16(dnskey_rdata) & 0x0001;
 }
 
-int kr_dnssec_key_from_rdata(struct dseckey **key, const knot_rdata_t *krdata, const knot_dname_t *kown)
+/** Return true if the DNSKEY is revoked. */
+bool kr_dnssec_key_revoked(const uint8_t *dnskey_rdata)
 {
-       assert(key);
+       return wire_read_u16(dnskey_rdata) & 0x0080;
+}
+
+int kr_dnssec_key_tag(uint16_t rrtype, const uint8_t *rdata, size_t rdlen)
+{
+       if (!rdata || rdlen == 0 || (rrtype != KNOT_RRTYPE_DS && rrtype != KNOT_RRTYPE_DNSKEY)) {
+               return kr_error(EINVAL);
+       }
+       if (rrtype == KNOT_RRTYPE_DS) {
+               return wire_read_u16(rdata);
+       } else if (rrtype == KNOT_RRTYPE_DNSKEY) {
+               struct dseckey *key = NULL;
+               int ret = kr_dnssec_key_from_rdata(&key, NULL, rdata, rdlen);
+               if (ret != 0) {
+                       return ret;
+               }
+               uint16_t keytag = dnssec_key_get_keytag((dnssec_key_t *)key);
+               kr_dnssec_key_free(&key);
+               return keytag;
+       } else {
+               return kr_error(EINVAL);
+       }
+}
+
+int kr_dnssec_key_from_rdata(struct dseckey **key, const knot_dname_t *kown, const uint8_t *rdata, size_t rdlen)
+{
+       if (!key || !rdata || rdlen == 0) {
+               return kr_error(EINVAL);
+       }
 
        dnssec_key_t *new_key = NULL;
-       dnssec_binary_t binary_key;
-       int ret;
+       const dnssec_binary_t binary_key = {
+               .size = rdlen,
+               .data = (uint8_t *)rdata
+       };
 
-       ret = dnssec_key_new(&new_key);
+       int ret = dnssec_key_new(&new_key);
        if (ret != DNSSEC_EOK) {
                return kr_error(ENOMEM);
        }
-
-       binary_key.size = knot_rdata_rdlen(krdata);
-       binary_key.data = knot_rdata_data(krdata);
-       if (!binary_key.size || !binary_key.data) {
-               dnssec_key_free(new_key);
-               return kr_error(KNOT_DNSSEC_ENOKEY);
-       }
        ret = dnssec_key_set_rdata(new_key, &binary_key);
        if (ret != DNSSEC_EOK) {
                dnssec_key_free(new_key);
                return kr_error(ENOMEM);
        }
-
-       ret = dnssec_key_set_dname(new_key, kown);
-       if (ret != DNSSEC_EOK) {
-               dnssec_key_free(new_key);
-               return kr_error(ENOMEM);
+       if (kown) {
+               ret = dnssec_key_set_dname(new_key, kown);
+               if (ret != DNSSEC_EOK) {
+                       dnssec_key_free(new_key);
+                       return kr_error(ENOMEM);
+               }
        }
 
        *key = (struct dseckey *) new_key;
index 50caf7ac8362a2a477b4cbca18d4fc292b8b92e0..b7d85e21487127b01f6c1d23ef03ac62a6dd64e9 100644 (file)
@@ -94,13 +94,21 @@ bool kr_dnssec_key_ksk(const uint8_t *dnskey_rdata);
 /** Return true if the DNSKEY is revoked. */
 bool kr_dnssec_key_revoked(const uint8_t *dnskey_rdata);
 
+/** Return DNSKEY tag.
+  * @param rrtype RR type (either DS or DNSKEY are supported)
+  * @param rdata  Key/digest RDATA.
+  * @param rdlen  RDATA length.
+  * @return Key tag (positive number), or an error code
+  */
+int kr_dnssec_key_tag(uint16_t rrtype, const uint8_t *rdata, size_t rdlen);
 /**
  * Construct a DNSSEC key.
- * @param key    Pointer to be set to newly created DNSSEC key.
- * @param krdata Key RDATA.
- * @param kown   DNSKEY RRSet owner name.
+ * @param key   Pointer to be set to newly created DNSSEC key.
+ * @param kown  DNSKEY owner name.
+ * @param rdata DNSKEY RDATA
+ * @param rdlen DNSKEY RDATA length
  */
-int kr_dnssec_key_from_rdata(struct dseckey **key, const knot_rdata_t *krdata, const knot_dname_t *kown);
+int kr_dnssec_key_from_rdata(struct dseckey **key, const knot_dname_t *kown, const uint8_t *rdata, size_t rdlen);
 
 /**
  * Frees the DNSSEC key.