00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
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];
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
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
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
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
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
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
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
00153 hash = uint8_fromregion(&sr);
00154 isc_region_consume(&sr, 1);
00155 sprintf(buf, "%u ", hash);
00156 RETERR(str_totext(buf, target));
00157
00158
00159 flags = uint8_fromregion(&sr);
00160 isc_region_consume(&sr, 1);
00161 sprintf(buf, "%u ", flags);
00162 RETERR(str_totext(buf, target));
00163
00164
00165 iterations = uint16_fromregion(&sr);
00166 isc_region_consume(&sr, 2);
00167 sprintf(buf, "%u ", iterations);
00168 RETERR(str_totext(buf, target));
00169
00170
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
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
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
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
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
00289
00290 if (!first && window <= lastwindow)
00291 RETERR(DNS_R_FORMERR);
00292
00293
00294
00295 if (len < 1 || len > 32)
00296 RETERR(DNS_R_FORMERR);
00297
00298
00299
00300 if (i + len > sr.length)
00301 RETERR(DNS_R_FORMERR);
00302
00303
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
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(®ion);
00404 nsec3->flags = uint8_consume_fromregion(®ion);
00405 nsec3->iterations = uint16_consume_fromregion(®ion);
00406
00407 nsec3->salt_length = uint8_consume_fromregion(®ion);
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(®ion, nsec3->salt_length);
00412
00413 nsec3->next_length = uint8_consume_fromregion(®ion);
00414 nsec3->next = mem_maybedup(mctx, region.base, nsec3->next_length);
00415 if (nsec3->next == NULL)
00416 goto cleanup;
00417 isc_region_consume(®ion, 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
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