]> git.ipfire.org Git - thirdparty/ldns.git/commitdiff
HIP
authorWillem Toorop <willem@NLnetLabs.nl>
Tue, 7 May 2013 14:22:45 +0000 (14:22 +0000)
committerWillem Toorop <willem@NLnetLabs.nl>
Tue, 7 May 2013 14:22:45 +0000 (14:22 +0000)
Changelog
host2str.c
host2wire.c
ldns/rr.h
rr.c
wire2host.c

index bb134b20ec222505ec91daffdea38d5497c6c929..f2443963edd3768fa413745503aa10f4af5848df 100644 (file)
--- a/Changelog
+++ b/Changelog
@@ -1,5 +1,6 @@
 1.6.17
-       * New RR types NINFO, RKEY, CDS, EUI48, EUI64, URI, CAA and TA.
+       * New RR types HIP, NINFO, RKEY, CDS, EUI48, EUI64, URI, CAA and TA.
+       * New RR type TKEY, but without operational practice.
        * Fix b{32,64}_{ntop,pton} detection and handling.
        * -T option for ldns-dane that has specific exit status for PKIX
          validated connections without (secure) TLSA records.
index a3bae5bc2ff61e9ba99e68b7fad2ffe272f60823..08d62b5bb5915899092eb4e6c501a68e47a25775 100644 (file)
@@ -813,10 +813,8 @@ ldns_rdf2buffer_str_nsec(ldns_buffer *output, const ldns_rdf *rdf)
                                }
                        }
                }
-
                pos += (uint16_t) bitmap_length;
        }
-
        return ldns_buffer_status(output);
 }
 
index de1e01e9ba3f074cf571496a6a9834117b4e30d2..c9d099c4ed1762b667d4f7295b1e341bf337f5a1 100644 (file)
@@ -81,6 +81,64 @@ ldns_rr_list2buffer_wire(ldns_buffer *buffer,const ldns_rr_list *rr_list)
        return ldns_buffer_status(buffer);
 }
 
+static ldns_status
+ldns_hip_rdata2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr)
+{
+       uint16_t i;
+
+       assert(ldns_rr_get_type(rr) == LDNS_RR_TYPE_HIP);
+
+       if (ldns_rr_rd_count(rr) >= 3 &&
+           ldns_rdf_get_type(ldns_rr_rdf(rr, 0)) == LDNS_RDF_TYPE_INT8 &&
+           ldns_rdf_get_type(ldns_rr_rdf(rr, 1)) == LDNS_RDF_TYPE_HEX  &&
+               ldns_rdf_size(ldns_rr_rdf(rr, 1)) >    0 &&
+               ldns_rdf_size(ldns_rr_rdf(rr, 1)) <= 255 &&
+           ldns_rdf_get_type(ldns_rr_rdf(rr, 2)) == LDNS_RDF_TYPE_B64) {
+
+               /* From RFC 5205 section 5. HIP RR Storage Format:
+                *************************************************
+
+       0                   1                   2                   3
+       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       |  HIT length   | PK algorithm  |          PK length            |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       |                                                               |
+       ~                           HIT                                 ~
+       |                                                               |
+       +                     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       |                     |                                         |
+       +-+-+-+-+-+-+-+-+-+-+-+                                         +
+       |                           Public Key                          |
+       ~                                                               ~
+       |                                                               |
+       +                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       |                               |                               |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+       |                                                               |
+       ~                       Rendezvous Servers                      ~
+       |                                                               |
+       +             +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       |             |
+       +-+-+-+-+-+-+-+                                                    */
+
+               ldns_buffer_write_u8(buffer,
+                                (uint8_t) ldns_rdf_size(ldns_rr_rdf(rr, 1)));
+               ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr, 0));
+               ldns_buffer_write_u16(buffer,
+                               (uint16_t) ldns_rdf_size(ldns_rr_rdf(rr, 2)));
+               i = 1;
+       } else {
+               i = 0;
+       }
+       while (i < ldns_rr_rd_count(rr)) {
+               (void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr, i));
+               i++;
+       }
+       return ldns_buffer_status(buffer);
+}
+
+
 ldns_status
 ldns_rr2buffer_wire_canonical(ldns_buffer *buffer,
                                                const ldns_rr *rr,
@@ -137,16 +195,19 @@ ldns_rr2buffer_wire_canonical(ldns_buffer *buffer,
                        ldns_buffer_write_u16(buffer, 0);
                }       
 
-               for (i = 0; i < ldns_rr_rd_count(rr); i++) {
-                       if (pre_rfc3597) {
-                               (void) ldns_rdf2buffer_wire_canonical(
+               if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_HIP) {
+                       (void) ldns_hip_rdata2buffer_wire(buffer, rr);
+               } else {
+                       for (i = 0; i < ldns_rr_rd_count(rr); i++) {
+                               if (pre_rfc3597) {
+                                       (void) ldns_rdf2buffer_wire_canonical(
                                                buffer, ldns_rr_rdf(rr, i));
-                       } else {
-                               (void) ldns_rdf2buffer_wire(
+                               } else {
+                                       (void) ldns_rdf2buffer_wire(
                                                buffer, ldns_rr_rdf(rr, i));
+                               }
                        }
                }
-               
                if (rdl_pos != 0) {
                        ldns_buffer_write_u16_at(buffer, rdl_pos,
                                                 ldns_buffer_position(buffer)
@@ -177,13 +238,15 @@ ldns_rr2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr, int section)
                        /* remember pos for later */
                        rdl_pos = ldns_buffer_position(buffer);
                        ldns_buffer_write_u16(buffer, 0);
-               }       
-
-               for (i = 0; i < ldns_rr_rd_count(rr); i++) {
-                       (void) ldns_rdf2buffer_wire(
-                                       buffer, ldns_rr_rdf(rr, i));
                }
-               
+               if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_HIP) {
+                       (void) ldns_hip_rdata2buffer_wire(buffer, rr);
+               } else {
+                       for (i = 0; i < ldns_rr_rd_count(rr); i++) {
+                               (void) ldns_rdf2buffer_wire(
+                                               buffer, ldns_rr_rdf(rr, i));
+                       }
+               }
                if (rdl_pos != 0) {
                        ldns_buffer_write_u16_at(buffer, rdl_pos,
                                                 ldns_buffer_position(buffer)
@@ -216,11 +279,13 @@ ldns_status
 ldns_rr_rdata2buffer_wire(ldns_buffer *buffer, const ldns_rr *rr)
 {
        uint16_t i;
+       if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_HIP) {
+               return ldns_hip_rdata2buffer_wire(buffer, rr);
+       }
        /* convert all the rdf's */
        for (i = 0; i < ldns_rr_rd_count(rr); i++) {
-               (void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr, i));
+               (void) ldns_rdf2buffer_wire(buffer, ldns_rr_rdf(rr,i));
        }
-
        return ldns_buffer_status(buffer);
 }
 
index 57015cee3e292d52b300a0795f070c8aa7b215f0..7d90a73499c5db54322e5f3ff0aef31d919fd4c7 100644 (file)
--- a/ldns/rr.h
+++ b/ldns/rr.h
@@ -181,6 +181,8 @@ enum ldns_enum_rr_type
        LDNS_RR_TYPE_NSEC3PARAMS = 51,
        LDNS_RR_TYPE_TLSA = 52, /* RFC 6698 */
 
+       LDNS_RR_TYPE_HIP = 55, /* RFC 5205 */
+
        /** draft-reid-dnsext-zs */
        LDNS_RR_TYPE_NINFO = 56,
        /** draft-reid-dnsext-rkey */
diff --git a/rr.c b/rr.c
index ea870ee084e2fa262594cfb8273fde772c4b35f6..2ec02e81c05fc4e6426903c0abd501830a08c0cf 100644 (file)
--- a/rr.c
+++ b/rr.c
@@ -341,22 +341,18 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str,
 
        for (done = false, r_cnt = 0; !done && r_cnt < r_max; r_cnt++) {
                quoted = false;
-               /* if type = B64, the field may contain spaces */
-               if (ldns_rr_descriptor_field_type(desc,
-                               r_cnt) == LDNS_RDF_TYPE_B64 ||
-                       ldns_rr_descriptor_field_type(desc,
-                               r_cnt) == LDNS_RDF_TYPE_HEX ||
-                       ldns_rr_descriptor_field_type(desc,
-                               r_cnt) == LDNS_RDF_TYPE_LOC ||
-                       ldns_rr_descriptor_field_type(desc,
-                               r_cnt) == LDNS_RDF_TYPE_WKS ||
-                       ldns_rr_descriptor_field_type(desc,
-                               r_cnt) == LDNS_RDF_TYPE_IPSECKEY ||
-                       ldns_rr_descriptor_field_type(desc,
-                               r_cnt) == LDNS_RDF_TYPE_NSEC) {
-                       delimiters = "\n\t";
-               } else {
-                       delimiters = "\n\t ";
+
+               switch (ldns_rr_descriptor_field_type(desc, r_cnt)) {
+               case LDNS_RDF_TYPE_B64        :
+               case LDNS_RDF_TYPE_HEX        : /* These rdf types may con- */
+               case LDNS_RDF_TYPE_LOC        : /* tain whitespace, only if */
+               case LDNS_RDF_TYPE_WKS        : /* it is the last rd field. */
+               case LDNS_RDF_TYPE_IPSECKEY   :
+               case LDNS_RDF_TYPE_NSEC       : if (r_cnt == r_max - 1) {
+                                                       delimiters = "\n\t";
+                                                       break;
+                                               }
+               default                       : delimiters = "\n\t "; 
                }
 
                if (ldns_rdf_type_maybe_quoted(
@@ -487,14 +483,18 @@ ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str,
 
                        case LDNS_RDF_TYPE_HEX:
                        case LDNS_RDF_TYPE_B64:
-                               /* can have spaces, and will always be the
-                                * last record of the rrdata. Read in the rest
+                               /* When this is the last rdata field, then the
+                                * rest should be read in (cause then these
+                                * rdf types may contain spaces).
                                 */
-                               c = ldns_bget_token(rd_buf, b64,
-                                               "\n", LDNS_MAX_RDFLEN);
-                               if (c != -1) {
-                                       rd = strncat(rd, b64, LDNS_MAX_RDFLEN
-                                                       - strlen(rd) - 1);
+                               if (r_cnt == r_max - 1) {
+                                       c = ldns_bget_token(rd_buf, b64,
+                                                       "\n", LDNS_MAX_RDFLEN);
+                                       if (c != -1) {
+                                               rd = strncat(rd, b64,
+                                                       LDNS_MAX_RDFLEN -
+                                                       strlen(rd) - 1);
+                                       }
                                }
                                r = ldns_rdf_new_frm_str(
                                                ldns_rr_descriptor_field_type(
@@ -1931,6 +1931,37 @@ static const ldns_rdf_type type_tlsa_wireformat[] = {
        LDNS_RDF_TYPE_INT8,
        LDNS_RDF_TYPE_HEX
 };
+
+/** 
+ * With HIP, wire and presentation format are out of step.
+ * In presentation format, we have:
+ * - a PK algorithm presented as integer in range [0..255]
+ * - a variable length HIT field presented as hexstring
+ * - a variable length Public Key field presented as Base64
+ *
+ * Unfortunately in the wireformat the lengths of the variable
+ * length HIT and Public Key fields do not directly preceed them.
+ * In stead we have:
+ * - 1 byte  HIT length: h
+ * - 1 byte  PK algorithm
+ * - 2 bytes Public Key length: p
+ * - h bytes HIT
+ * - p bytes Public Key
+ *
+ * In ldns those deviations from the conventions for rdata fields are best 
+ * tackeled by letting the array refered to by the descriptor for HIP represent
+ * host format only.
+ *
+ * BEWARE! Unlike other RR types, actual HIP wire format does not directly
+ * follow the RDF types enumerated in the array pointed to by _wireformat in
+ * its descriptor record.
+ */
+static const ldns_rdf_type type_hip_hostformat[] = {
+       LDNS_RDF_TYPE_INT8,
+       LDNS_RDF_TYPE_HEX,
+       LDNS_RDF_TYPE_B64
+};
+
 static const ldns_rdf_type type_nid_wireformat[] = {
        LDNS_RDF_TYPE_INT16,
        LDNS_RDF_TYPE_ILNP64
@@ -2066,7 +2097,7 @@ static ldns_rr_descriptor rdata_field_descriptors[] = {
        /* 46 */
        {LDNS_RR_TYPE_RRSIG, "RRSIG", 9, 9, type_rrsig_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
        /* 47 */
-       {LDNS_RR_TYPE_NSEC, "NSEC", 1, 2, type_nsec_wireformat, LDNS_RDF_TYPE_NSEC, LDNS_RR_NO_COMPRESS, 1 },
+       {LDNS_RR_TYPE_NSEC, "NSEC", 1, 2, type_nsec_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 1 },
        /* 48 */
        {LDNS_RR_TYPE_DNSKEY, "DNSKEY", 4, 4, type_dnskey_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
        /* 49 */
@@ -2080,7 +2111,17 @@ static ldns_rr_descriptor rdata_field_descriptors[] = {
 
 {LDNS_RR_TYPE_NULL, "TYPE53", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
 {LDNS_RR_TYPE_NULL, "TYPE54", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
-{LDNS_RR_TYPE_NULL, "TYPE55", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
+
+       /* 55
+        * Hip ends with 0 or more Rendezvous Servers represented as dname's.
+        * Hence the LDNS_RDF_TYPE_DNAME _variable field and the _maximum field
+        * set to 0.
+        *
+        * BEWARE! Unlike other RR types, actual HIP wire format does not 
+        * directly follow the RDF types enumerated in the array pointed to
+        * by _wireformat. For more info see type_hip_hostformat declaration.
+        */
+       {LDNS_RR_TYPE_HIP, "HIP", 3, 3, type_hip_hostformat, LDNS_RDF_TYPE_DNAME, LDNS_RR_NO_COMPRESS, 0 },
 
        /* 56 */
        {LDNS_RR_TYPE_NINFO, "NINFO", 1, 0, NULL, LDNS_RDF_TYPE_STR, LDNS_RR_NO_COMPRESS, 0 },
index d018e7bd88d436d665631f875990da93155d7aee..9ba2c3fbd882ea2544355dae4329cd29226be4f4 100644 (file)
@@ -165,8 +165,14 @@ ldns_wire2rdf(ldns_rr *rr, const uint8_t *wire, size_t max, size_t *pos)
        uint16_t rd_length;
        ldns_rdf *cur_rdf = NULL;
        ldns_rdf_type cur_rdf_type;
-       const ldns_rr_descriptor *descriptor = ldns_rr_descript(ldns_rr_get_type(rr));
+       const ldns_rr_descriptor *descriptor;
        ldns_status status;
+       uint8_t  hip_hit_length;
+       uint16_t hip_pubkey_length;
+
+       assert(rr != NULL);
+
+       descriptor = ldns_rr_descript(ldns_rr_get_type(rr));
 
        if (*pos + 2 > max) {
                return LDNS_STATUS_PACKET_OVERFLOW;
@@ -181,14 +187,86 @@ ldns_wire2rdf(ldns_rr *rr, const uint8_t *wire, size_t max, size_t *pos)
 
        end = *pos + (size_t) rd_length;
 
-       for (rdf_index = 0;
-            rdf_index < ldns_rr_descriptor_maximum(descriptor); rdf_index++) {
-               if (*pos >= end) {
-                       break;
+       if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_HIP) {
+
+               /* From RFC 5205 section 5. HIP RR Storage Format:
+                *************************************************
+
+       0                   1                   2                   3
+       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       |  HIT length   | PK algorithm  |          PK length            |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       |                                                               |
+       ~                           HIT                                 ~
+       |                                                               |
+       +                     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       |                     |                                         |
+       +-+-+-+-+-+-+-+-+-+-+-+                                         +
+       |                           Public Key                          |
+       ~                                                               ~
+       |                                                               |
+       +                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       |                               |                               |
+       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
+       |                                                               |
+       ~                       Rendezvous Servers                      ~
+       |                                                               |
+       +             +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+       |             |
+       +-+-+-+-+-+-+-+                                                    */
+
+               /* Space for HIT length, PK algorithm, PK length available? */
+               if (*pos + 4 > end) {
+                       return LDNS_STATUS_PACKET_OVERFLOW;
+               }
+               /* Get HIT length and PK length */
+               hip_hit_length = wire[*pos];
+               hip_pubkey_length = ldns_read_uint16(&wire[*pos + 2]);
+
+               /* Space for HIT length, PK algorithm, PK length, HIT and
+                * Public Key  available?
+                */
+               if (*pos + 4 + hip_hit_length + hip_pubkey_length > end) {
+                       return LDNS_STATUS_PACKET_OVERFLOW;
+               }
+               /* Read PK algorithm rdf */
+               cur_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_INT8,
+                               1, &wire[*pos + 1]);
+               if (cur_rdf) {
+                       ldns_rr_push_rdf(rr, cur_rdf);
+               }
+               *pos += 4;
+
+               /* Read HIT rdf */
+               cur_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX,
+                               hip_hit_length, &wire[*pos]);
+               if (cur_rdf) {
+                       ldns_rr_push_rdf(rr, cur_rdf);
+               }
+               *pos += hip_hit_length;
+
+               /* Read Public Key rdf */
+               cur_rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64,
+                               hip_pubkey_length, &wire[*pos]);
+               if (cur_rdf) {
+                       ldns_rr_push_rdf(rr, cur_rdf);
                }
+               *pos += hip_pubkey_length;
+
+               /* Variable number of Rendezvous Servers may follow */
+               rdf_index = 3;
+       } else {
+               rdf_index = 0;
+       }
+       while (*pos < end &&
+                       rdf_index < ldns_rr_descriptor_maximum(descriptor)) {
+
                cur_rdf_length = 0;
 
-               cur_rdf_type = ldns_rr_descriptor_field_type(descriptor, rdf_index);
+               cur_rdf_type = ldns_rr_descriptor_field_type(
+                               descriptor, rdf_index);
+
                /* handle special cases immediately, set length
                   for fixed length rdata and do them below */
                switch (cur_rdf_type) {
@@ -244,7 +322,11 @@ ldns_wire2rdf(ldns_rr *rr, const uint8_t *wire, size_t max, size_t *pos)
                        }
                        break;
                case LDNS_RDF_TYPE_INT16_DATA:
-                       cur_rdf_length = (size_t) ldns_read_uint16(&wire[*pos]) + 2;
+                       if (*pos + 2 > end) {
+                               return LDNS_STATUS_PACKET_OVERFLOW;
+                       }
+                       cur_rdf_length =
+                               (size_t) ldns_read_uint16(&wire[*pos]) + 2;
                        break;
                case LDNS_RDF_TYPE_B32_EXT:
                case LDNS_RDF_TYPE_NSEC3_NEXT_OWNER:
@@ -283,7 +365,8 @@ ldns_wire2rdf(ldns_rr *rr, const uint8_t *wire, size_t max, size_t *pos)
                        }
                        memcpy(data, &wire[*pos], cur_rdf_length);
 
-                       cur_rdf = ldns_rdf_new(cur_rdf_type, cur_rdf_length, data);
+                       cur_rdf = ldns_rdf_new(cur_rdf_type,
+                                       cur_rdf_length, data);
                        *pos = *pos + cur_rdf_length;
                }
 
@@ -291,7 +374,11 @@ ldns_wire2rdf(ldns_rr *rr, const uint8_t *wire, size_t max, size_t *pos)
                        ldns_rr_push_rdf(rr, cur_rdf);
                        cur_rdf = NULL;
                }
-       }
+
+               rdf_index++;
+
+       } /* while (rdf_index < ldns_rr_descriptor_maximum(descriptor)) */
+
 
        return LDNS_STATUS_OK;
 }