nsec3_50.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2008, 2009, 2011, 2012, 2014, 2015  Internet Systems Consortium, Inc. ("ISC")
00003  *
00004  * Permission to use, copy, modify, and/or distribute this software for any
00005  * purpose with or without fee is hereby granted, provided that the above
00006  * copyright notice and this permission notice appear in all copies.
00007  *
00008  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00009  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00010  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00011  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00012  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00013  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00014  * PERFORMANCE OF THIS SOFTWARE.
00015  */
00016 
00017 /* $Id$ */
00018 
00019 /*
00020  * Copyright (C) 2004  Nominet, Ltd.
00021  *
00022  * Permission to use, copy, modify, and distribute this software for any
00023  * purpose with or without fee is hereby granted, provided that the above
00024  * copyright notice and this permission notice appear in all copies.
00025  *
00026  * THE SOFTWARE IS PROVIDED "AS IS" AND NOMINET DISCLAIMS ALL WARRANTIES WITH
00027  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00028  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00029  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00030  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00031  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00032  * PERFORMANCE OF THIS SOFTWARE.
00033  */
00034 
00035 /* RFC 5155 */
00036 
00037 #ifndef RDATA_GENERIC_NSEC3_50_C
00038 #define RDATA_GENERIC_NSEC3_50_C
00039 
00040 #include <isc/iterated_hash.h>
00041 #include <isc/base32.h>
00042 
00043 #define RRTYPE_NSEC3_ATTRIBUTES DNS_RDATATYPEATTR_DNSSEC
00044 
00045 static inline isc_result_t
00046 fromtext_nsec3(ARGS_FROMTEXT) {
00047         isc_token_t token;
00048         unsigned char bm[8*1024]; /* 64k bits */
00049         dns_rdatatype_t covered;
00050         int octet;
00051         int window;
00052         unsigned int flags;
00053         unsigned char hashalg;
00054         isc_buffer_t b;
00055 
00056         REQUIRE(type == 50);
00057 
00058         UNUSED(type);
00059         UNUSED(rdclass);
00060         UNUSED(callbacks);
00061         UNUSED(origin);
00062         UNUSED(options);
00063 
00064         /* Hash. */
00065         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
00066                                       ISC_FALSE));
00067         RETTOK(dns_hashalg_fromtext(&hashalg, &token.value.as_textregion));
00068         RETERR(uint8_tobuffer(hashalg, target));
00069 
00070         /* Flags. */
00071         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
00072                                       ISC_FALSE));
00073         flags = token.value.as_ulong;
00074         if (flags > 255U)
00075                 RETTOK(ISC_R_RANGE);
00076         RETERR(uint8_tobuffer(flags, target));
00077 
00078         /* Iterations. */
00079         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
00080                                       ISC_FALSE));
00081         if (token.value.as_ulong > 0xffffU)
00082                 RETTOK(ISC_R_RANGE);
00083         RETERR(uint16_tobuffer(token.value.as_ulong, target));
00084 
00085         /* salt */
00086         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
00087                                       ISC_FALSE));
00088         if (token.value.as_textregion.length > (255*2))
00089                 RETTOK(DNS_R_TEXTTOOLONG);
00090         if (strcmp(DNS_AS_STR(token), "-") == 0) {
00091                 RETERR(uint8_tobuffer(0, target));
00092         } else {
00093                 RETERR(uint8_tobuffer(strlen(DNS_AS_STR(token)) / 2, target));
00094                 RETERR(isc_hex_decodestring(DNS_AS_STR(token), target));
00095         }
00096 
00097         /*
00098          * Next hash a single base32hex word.
00099          */
00100         RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
00101                                       ISC_FALSE));
00102         isc_buffer_init(&b, bm, sizeof(bm));
00103         RETTOK(isc_base32hexnp_decodestring(DNS_AS_STR(token), &b));
00104         if (isc_buffer_usedlength(&b) > 0xffU)
00105                 RETTOK(ISC_R_RANGE);
00106         RETERR(uint8_tobuffer(isc_buffer_usedlength(&b), target));
00107         RETERR(mem_tobuffer(target, &bm, isc_buffer_usedlength(&b)));
00108 
00109         memset(bm, 0, sizeof(bm));
00110         do {
00111                 RETERR(isc_lex_getmastertoken(lexer, &token,
00112                                               isc_tokentype_string, ISC_TRUE));
00113                 if (token.type != isc_tokentype_string)
00114                         break;
00115                 RETTOK(dns_rdatatype_fromtext(&covered,
00116                                               &token.value.as_textregion));
00117                 bm[covered/8] |= (0x80>>(covered%8));
00118         } while (1);
00119         isc_lex_ungettoken(lexer, &token);
00120         for (window = 0; window < 256 ; window++) {
00121                 /*
00122                  * Find if we have a type in this window.
00123                  */
00124                 for (octet = 31; octet >= 0; octet--)
00125                         if (bm[window * 32 + octet] != 0)
00126                                 break;
00127                 if (octet < 0)
00128                         continue;
00129                 RETERR(uint8_tobuffer(window, target));
00130                 RETERR(uint8_tobuffer(octet + 1, target));
00131                 RETERR(mem_tobuffer(target, &bm[window * 32], octet + 1));
00132         }
00133         return (ISC_R_SUCCESS);
00134 }
00135 
00136 static inline isc_result_t
00137 totext_nsec3(ARGS_TOTEXT) {
00138         isc_region_t sr;
00139         unsigned int i, j, k;
00140         unsigned int window, len;
00141         unsigned char hash;
00142         unsigned char flags;
00143         char buf[sizeof("TYPE65535")];
00144         isc_uint32_t iterations;
00145         isc_boolean_t first;
00146 
00147         REQUIRE(rdata->type == 50);
00148         REQUIRE(rdata->length != 0);
00149 
00150         dns_rdata_toregion(rdata, &sr);
00151 
00152         /* Hash */
00153         hash = uint8_fromregion(&sr);
00154         isc_region_consume(&sr, 1);
00155         sprintf(buf, "%u ", hash);
00156         RETERR(str_totext(buf, target));
00157 
00158         /* Flags */
00159         flags = uint8_fromregion(&sr);
00160         isc_region_consume(&sr, 1);
00161         sprintf(buf, "%u ", flags);
00162         RETERR(str_totext(buf, target));
00163 
00164         /* Iterations */
00165         iterations = uint16_fromregion(&sr);
00166         isc_region_consume(&sr, 2);
00167         sprintf(buf, "%u ", iterations);
00168         RETERR(str_totext(buf, target));
00169 
00170         /* Salt */
00171         j = uint8_fromregion(&sr);
00172         isc_region_consume(&sr, 1);
00173         INSIST(j <= sr.length);
00174 
00175         if (j != 0) {
00176                 i = sr.length;
00177                 sr.length = j;
00178                 RETERR(isc_hex_totext(&sr, 1, "", target));
00179                 sr.length = i - j;
00180         } else
00181                 RETERR(str_totext("-", target));
00182 
00183         if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
00184                 RETERR(str_totext(" (", target));
00185         RETERR(str_totext(tctx->linebreak, target));
00186 
00187         /* Next hash */
00188         j = uint8_fromregion(&sr);
00189         isc_region_consume(&sr, 1);
00190         INSIST(j <= sr.length);
00191 
00192         i = sr.length;
00193         sr.length = j;
00194         RETERR(isc_base32hexnp_totext(&sr, 1, "", target));
00195         sr.length = i - j;
00196 
00197         if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) == 0)
00198                 RETERR(str_totext(" ", target));
00199 
00200         /* Types covered */
00201         first = ISC_TRUE;
00202         for (i = 0; i < sr.length; i += len) {
00203                 if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0) {
00204                         RETERR(str_totext(tctx->linebreak, target));
00205                         first = ISC_TRUE;
00206                 }
00207                 INSIST(i + 2 <= sr.length);
00208                 window = sr.base[i];
00209                 len = sr.base[i + 1];
00210                 INSIST(len > 0 && len <= 32);
00211                 i += 2;
00212                 INSIST(i + len <= sr.length);
00213                 for (j = 0; j < len; j++) {
00214                         dns_rdatatype_t t;
00215                         if (sr.base[i + j] == 0)
00216                                 continue;
00217                         for (k = 0; k < 8; k++) {
00218                                 if ((sr.base[i + j] & (0x80 >> k)) == 0)
00219                                         continue;
00220                                 t = window * 256 + j * 8 + k;
00221                                 if (!first)
00222                                         RETERR(str_totext(" ", target));
00223                                 first = ISC_FALSE;
00224                                 if (dns_rdatatype_isknown(t)) {
00225                                         RETERR(dns_rdatatype_totext(t, target));
00226                                 } else {
00227                                         sprintf(buf, "TYPE%u", t);
00228                                         RETERR(str_totext(buf, target));
00229                                 }
00230                         }
00231                 }
00232         }
00233 
00234         if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
00235                 RETERR(str_totext(" )", target));
00236 
00237         return (ISC_R_SUCCESS);
00238 }
00239 
00240 static inline isc_result_t
00241 fromwire_nsec3(ARGS_FROMWIRE) {
00242         isc_region_t sr, rr;
00243         unsigned int window, lastwindow = 0;
00244         unsigned int len;
00245         unsigned int saltlen, hashlen;
00246         isc_boolean_t first = ISC_TRUE;
00247         unsigned int i;
00248 
00249         REQUIRE(type == 50);
00250 
00251         UNUSED(type);
00252         UNUSED(rdclass);
00253         UNUSED(options);
00254         UNUSED(dctx);
00255 
00256         isc_buffer_activeregion(source, &sr);
00257         rr = sr;
00258 
00259         /* hash(1), flags(1), iteration(2), saltlen(1) */
00260         if (sr.length < 5U)
00261                 RETERR(DNS_R_FORMERR);
00262         saltlen = sr.base[4];
00263         isc_region_consume(&sr, 5);
00264 
00265         if (sr.length < saltlen)
00266                 RETERR(DNS_R_FORMERR);
00267         isc_region_consume(&sr, saltlen);
00268 
00269         if (sr.length < 1U)
00270                 RETERR(DNS_R_FORMERR);
00271         hashlen = sr.base[0];
00272         isc_region_consume(&sr, 1);
00273 
00274         if (sr.length < hashlen)
00275                 RETERR(DNS_R_FORMERR);
00276         isc_region_consume(&sr, hashlen);
00277 
00278         for (i = 0; i < sr.length; i += len) {
00279                 /*
00280                  * Check for overflow.
00281                  */
00282                 if (i + 2 > sr.length)
00283                         RETERR(DNS_R_FORMERR);
00284                 window = sr.base[i];
00285                 len = sr.base[i + 1];
00286                 i += 2;
00287                 /*
00288                  * Check that bitmap windows are in the correct order.
00289                  */
00290                 if (!first && window <= lastwindow)
00291                         RETERR(DNS_R_FORMERR);
00292                 /*
00293                  * Check for legal lengths.
00294                  */
00295                 if (len < 1 || len > 32)
00296                         RETERR(DNS_R_FORMERR);
00297                 /*
00298                  * Check for overflow.
00299                  */
00300                 if (i + len > sr.length)
00301                         RETERR(DNS_R_FORMERR);
00302                 /*
00303                  * The last octet of the bitmap must be non zero.
00304                  */
00305                 if (sr.base[i + len - 1] == 0)
00306                         RETERR(DNS_R_FORMERR);
00307                 lastwindow = window;
00308                 first = ISC_FALSE;
00309         }
00310         if (i != sr.length)
00311                 return (DNS_R_EXTRADATA);
00312         RETERR(mem_tobuffer(target, rr.base, rr.length));
00313         isc_buffer_forward(source, rr.length);
00314         return (ISC_R_SUCCESS);
00315 }
00316 
00317 static inline isc_result_t
00318 towire_nsec3(ARGS_TOWIRE) {
00319         isc_region_t sr;
00320 
00321         REQUIRE(rdata->type == 50);
00322         REQUIRE(rdata->length != 0);
00323 
00324         UNUSED(cctx);
00325 
00326         dns_rdata_toregion(rdata, &sr);
00327         return (mem_tobuffer(target, sr.base, sr.length));
00328 }
00329 
00330 static inline int
00331 compare_nsec3(ARGS_COMPARE) {
00332         isc_region_t r1;
00333         isc_region_t r2;
00334 
00335         REQUIRE(rdata1->type == rdata2->type);
00336         REQUIRE(rdata1->rdclass == rdata2->rdclass);
00337         REQUIRE(rdata1->type == 50);
00338         REQUIRE(rdata1->length != 0);
00339         REQUIRE(rdata2->length != 0);
00340 
00341         dns_rdata_toregion(rdata1, &r1);
00342         dns_rdata_toregion(rdata2, &r2);
00343         return (isc_region_compare(&r1, &r2));
00344 }
00345 
00346 static inline isc_result_t
00347 fromstruct_nsec3(ARGS_FROMSTRUCT) {
00348         dns_rdata_nsec3_t *nsec3 = source;
00349         unsigned int i, len, window, lastwindow = 0;
00350         isc_boolean_t first = ISC_TRUE;
00351 
00352         REQUIRE(type == 50);
00353         REQUIRE(source != NULL);
00354         REQUIRE(nsec3->common.rdtype == type);
00355         REQUIRE(nsec3->common.rdclass == rdclass);
00356         REQUIRE(nsec3->typebits != NULL || nsec3->len == 0);
00357         REQUIRE(nsec3->hash == dns_hash_sha1);
00358 
00359         UNUSED(type);
00360         UNUSED(rdclass);
00361 
00362         RETERR(uint8_tobuffer(nsec3->hash, target));
00363         RETERR(uint8_tobuffer(nsec3->flags, target));
00364         RETERR(uint16_tobuffer(nsec3->iterations, target));
00365         RETERR(uint8_tobuffer(nsec3->salt_length, target));
00366         RETERR(mem_tobuffer(target, nsec3->salt, nsec3->salt_length));
00367         RETERR(uint8_tobuffer(nsec3->next_length, target));
00368         RETERR(mem_tobuffer(target, nsec3->next, nsec3->next_length));
00369 
00370         /*
00371          * Perform sanity check.
00372          */
00373         for (i = 0; i < nsec3->len ; i += len) {
00374                 INSIST(i + 2 <= nsec3->len);
00375                 window = nsec3->typebits[i];
00376                 len = nsec3->typebits[i+1];
00377                 i += 2;
00378                 INSIST(first || window > lastwindow);
00379                 INSIST(len > 0 && len <= 32);
00380                 INSIST(i + len <= nsec3->len);
00381                 INSIST(nsec3->typebits[i + len - 1] != 0);
00382                 lastwindow = window;
00383                 first = ISC_FALSE;
00384         }
00385         return (mem_tobuffer(target, nsec3->typebits, nsec3->len));
00386 }
00387 
00388 static inline isc_result_t
00389 tostruct_nsec3(ARGS_TOSTRUCT) {
00390         isc_region_t region;
00391         dns_rdata_nsec3_t *nsec3 = target;
00392 
00393         REQUIRE(rdata->type == 50);
00394         REQUIRE(target != NULL);
00395         REQUIRE(rdata->length != 0);
00396 
00397         nsec3->common.rdclass = rdata->rdclass;
00398         nsec3->common.rdtype = rdata->type;
00399         ISC_LINK_INIT(&nsec3->common, link);
00400 
00401         region.base = rdata->data;
00402         region.length = rdata->length;
00403         nsec3->hash = uint8_consume_fromregion(&region);
00404         nsec3->flags = uint8_consume_fromregion(&region);
00405         nsec3->iterations = uint16_consume_fromregion(&region);
00406 
00407         nsec3->salt_length = uint8_consume_fromregion(&region);
00408         nsec3->salt = mem_maybedup(mctx, region.base, nsec3->salt_length);
00409         if (nsec3->salt == NULL)
00410                 return (ISC_R_NOMEMORY);
00411         isc_region_consume(&region, nsec3->salt_length);
00412 
00413         nsec3->next_length = uint8_consume_fromregion(&region);
00414         nsec3->next = mem_maybedup(mctx, region.base, nsec3->next_length);
00415         if (nsec3->next == NULL)
00416                 goto cleanup;
00417         isc_region_consume(&region, nsec3->next_length);
00418 
00419         nsec3->len = region.length;
00420         nsec3->typebits = mem_maybedup(mctx, region.base, region.length);
00421         if (nsec3->typebits == NULL)
00422                 goto cleanup;
00423 
00424         nsec3->mctx = mctx;
00425         return (ISC_R_SUCCESS);
00426 
00427   cleanup:
00428         if (nsec3->next != NULL)
00429                 isc_mem_free(mctx, nsec3->next);
00430         isc_mem_free(mctx, nsec3->salt);
00431         return (ISC_R_NOMEMORY);
00432 }
00433 
00434 static inline void
00435 freestruct_nsec3(ARGS_FREESTRUCT) {
00436         dns_rdata_nsec3_t *nsec3 = source;
00437 
00438         REQUIRE(source != NULL);
00439         REQUIRE(nsec3->common.rdtype == 50);
00440 
00441         if (nsec3->mctx == NULL)
00442                 return;
00443 
00444         if (nsec3->salt != NULL)
00445                 isc_mem_free(nsec3->mctx, nsec3->salt);
00446         if (nsec3->next != NULL)
00447                 isc_mem_free(nsec3->mctx, nsec3->next);
00448         if (nsec3->typebits != NULL)
00449                 isc_mem_free(nsec3->mctx, nsec3->typebits);
00450         nsec3->mctx = NULL;
00451 }
00452 
00453 static inline isc_result_t
00454 additionaldata_nsec3(ARGS_ADDLDATA) {
00455         REQUIRE(rdata->type == 50);
00456 
00457         UNUSED(rdata);
00458         UNUSED(add);
00459         UNUSED(arg);
00460 
00461         return (ISC_R_SUCCESS);
00462 }
00463 
00464 static inline isc_result_t
00465 digest_nsec3(ARGS_DIGEST) {
00466         isc_region_t r;
00467 
00468         REQUIRE(rdata->type == 50);
00469 
00470         dns_rdata_toregion(rdata, &r);
00471         return ((digest)(arg, &r));
00472 }
00473 
00474 static inline isc_boolean_t
00475 checkowner_nsec3(ARGS_CHECKOWNER) {
00476         unsigned char owner[NSEC3_MAX_HASH_LENGTH];
00477         isc_buffer_t buffer;
00478         dns_label_t label;
00479 
00480         REQUIRE(type == 50);
00481 
00482         UNUSED(type);
00483         UNUSED(rdclass);
00484         UNUSED(wildcard);
00485 
00486         /*
00487          * First label is a base32hex string without padding.
00488          */
00489         dns_name_getlabel(name, 0, &label);
00490         isc_region_consume(&label, 1);
00491         isc_buffer_init(&buffer, owner, sizeof(owner));
00492         if (isc_base32hexnp_decoderegion(&label, &buffer) == ISC_R_SUCCESS)
00493                 return (ISC_TRUE);
00494 
00495         return (ISC_FALSE);
00496 }
00497 
00498 static inline isc_boolean_t
00499 checknames_nsec3(ARGS_CHECKNAMES) {
00500 
00501         REQUIRE(rdata->type == 50);
00502 
00503         UNUSED(rdata);
00504         UNUSED(owner);
00505         UNUSED(bad);
00506 
00507         return (ISC_TRUE);
00508 }
00509 
00510 static inline int
00511 casecompare_nsec3(ARGS_COMPARE) {
00512         return (compare_nsec3(rdata1, rdata2));
00513 }
00514 
00515 #endif  /* RDATA_GENERIC_NSEC3_50_C */

Generated on Tue Apr 28 17:41:00 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha