00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <config.h>
00023
00024 #include <isc/log.h>
00025 #include <isc/string.h>
00026 #include <isc/util.h>
00027
00028 #include <dns/db.h>
00029 #include <dns/nsec.h>
00030 #include <dns/rdata.h>
00031 #include <dns/rdatalist.h>
00032 #include <dns/rdataset.h>
00033 #include <dns/rdatasetiter.h>
00034 #include <dns/rdatastruct.h>
00035 #include <dns/result.h>
00036
00037 #include <dst/dst.h>
00038
00039 #define RETERR(x) do { \
00040 result = (x); \
00041 if (result != ISC_R_SUCCESS) \
00042 goto failure; \
00043 } while (0)
00044
00045 void
00046 dns_nsec_setbit(unsigned char *array, unsigned int type, unsigned int bit) {
00047 unsigned int shift, mask;
00048
00049 shift = 7 - (type % 8);
00050 mask = 1 << shift;
00051
00052 if (bit != 0)
00053 array[type / 8] |= mask;
00054 else
00055 array[type / 8] &= (~mask & 0xFF);
00056 }
00057
00058 isc_boolean_t
00059 dns_nsec_isset(const unsigned char *array, unsigned int type) {
00060 unsigned int byte, shift, mask;
00061
00062 byte = array[type / 8];
00063 shift = 7 - (type % 8);
00064 mask = 1 << shift;
00065
00066 return (ISC_TF(byte & mask));
00067 }
00068
00069 unsigned int
00070 dns_nsec_compressbitmap(unsigned char *map, const unsigned char *raw,
00071 unsigned int max_type)
00072 {
00073 unsigned char *start = map;
00074 unsigned int window;
00075 int octet;
00076
00077 if (raw == NULL)
00078 return (0);
00079
00080 for (window = 0; window < 256; window++) {
00081 if (window * 256 > max_type)
00082 break;
00083 for (octet = 31; octet >= 0; octet--)
00084 if (*(raw + octet) != 0)
00085 break;
00086 if (octet < 0) {
00087 raw += 32;
00088 continue;
00089 }
00090 *map++ = window;
00091 *map++ = octet + 1;
00092
00093
00094
00095 memmove(map, raw, octet + 1);
00096 map += octet + 1;
00097 raw += 32;
00098 }
00099 return (unsigned int)(map - start);
00100 }
00101
00102 isc_result_t
00103 dns_nsec_buildrdata(dns_db_t *db, dns_dbversion_t *version,
00104 dns_dbnode_t *node, dns_name_t *target,
00105 unsigned char *buffer, dns_rdata_t *rdata)
00106 {
00107 isc_result_t result;
00108 dns_rdataset_t rdataset;
00109 isc_region_t r;
00110 unsigned int i;
00111
00112 unsigned char *nsec_bits, *bm;
00113 unsigned int max_type;
00114 dns_rdatasetiter_t *rdsiter;
00115
00116 memset(buffer, 0, DNS_NSEC_BUFFERSIZE);
00117 dns_name_toregion(target, &r);
00118 memmove(buffer, r.base, r.length);
00119 r.base = buffer;
00120
00121
00122
00123
00124 bm = r.base + r.length + 512;
00125 nsec_bits = r.base + r.length;
00126 dns_nsec_setbit(bm, dns_rdatatype_rrsig, 1);
00127 dns_nsec_setbit(bm, dns_rdatatype_nsec, 1);
00128 max_type = dns_rdatatype_nsec;
00129 dns_rdataset_init(&rdataset);
00130 rdsiter = NULL;
00131 result = dns_db_allrdatasets(db, node, version, 0, &rdsiter);
00132 if (result != ISC_R_SUCCESS)
00133 return (result);
00134 for (result = dns_rdatasetiter_first(rdsiter);
00135 result == ISC_R_SUCCESS;
00136 result = dns_rdatasetiter_next(rdsiter))
00137 {
00138 dns_rdatasetiter_current(rdsiter, &rdataset);
00139 if (rdataset.type != dns_rdatatype_nsec &&
00140 rdataset.type != dns_rdatatype_nsec3 &&
00141 rdataset.type != dns_rdatatype_rrsig) {
00142 if (rdataset.type > max_type)
00143 max_type = rdataset.type;
00144 dns_nsec_setbit(bm, rdataset.type, 1);
00145 }
00146 dns_rdataset_disassociate(&rdataset);
00147 }
00148
00149
00150
00151
00152 if (dns_nsec_isset(bm, dns_rdatatype_ns) &&
00153 ! dns_nsec_isset(bm, dns_rdatatype_soa)) {
00154 for (i = 0; i <= max_type; i++) {
00155 if (dns_nsec_isset(bm, i) &&
00156 ! dns_rdatatype_iszonecutauth((dns_rdatatype_t)i))
00157 dns_nsec_setbit(bm, i, 0);
00158 }
00159 }
00160
00161 dns_rdatasetiter_destroy(&rdsiter);
00162 if (result != ISC_R_NOMORE)
00163 return (result);
00164
00165 nsec_bits += dns_nsec_compressbitmap(nsec_bits, bm, max_type);
00166
00167 r.length = (unsigned int)(nsec_bits - r.base);
00168 INSIST(r.length <= DNS_NSEC_BUFFERSIZE);
00169 dns_rdata_fromregion(rdata,
00170 dns_db_class(db),
00171 dns_rdatatype_nsec,
00172 &r);
00173
00174 return (ISC_R_SUCCESS);
00175 }
00176
00177 isc_result_t
00178 dns_nsec_build(dns_db_t *db, dns_dbversion_t *version, dns_dbnode_t *node,
00179 dns_name_t *target, dns_ttl_t ttl)
00180 {
00181 isc_result_t result;
00182 dns_rdata_t rdata = DNS_RDATA_INIT;
00183 unsigned char data[DNS_NSEC_BUFFERSIZE];
00184 dns_rdatalist_t rdatalist;
00185 dns_rdataset_t rdataset;
00186
00187 dns_rdataset_init(&rdataset);
00188 dns_rdata_init(&rdata);
00189
00190 RETERR(dns_nsec_buildrdata(db, version, node, target, data, &rdata));
00191
00192 dns_rdatalist_init(&rdatalist);
00193 rdatalist.rdclass = dns_db_class(db);
00194 rdatalist.type = dns_rdatatype_nsec;
00195 rdatalist.ttl = ttl;
00196 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link);
00197 RETERR(dns_rdatalist_tordataset(&rdatalist, &rdataset));
00198 result = dns_db_addrdataset(db, node, version, 0, &rdataset,
00199 0, NULL);
00200 if (result == DNS_R_UNCHANGED)
00201 result = ISC_R_SUCCESS;
00202
00203 failure:
00204 if (dns_rdataset_isassociated(&rdataset))
00205 dns_rdataset_disassociate(&rdataset);
00206 return (result);
00207 }
00208
00209 isc_boolean_t
00210 dns_nsec_typepresent(dns_rdata_t *nsec, dns_rdatatype_t type) {
00211 dns_rdata_nsec_t nsecstruct;
00212 isc_result_t result;
00213 isc_boolean_t present;
00214 unsigned int i, len, window;
00215
00216 REQUIRE(nsec != NULL);
00217 REQUIRE(nsec->type == dns_rdatatype_nsec);
00218
00219
00220 result = dns_rdata_tostruct(nsec, &nsecstruct, NULL);
00221 INSIST(result == ISC_R_SUCCESS);
00222
00223 present = ISC_FALSE;
00224 for (i = 0; i < nsecstruct.len; i += len) {
00225 INSIST(i + 2 <= nsecstruct.len);
00226 window = nsecstruct.typebits[i];
00227 len = nsecstruct.typebits[i + 1];
00228 INSIST(len > 0 && len <= 32);
00229 i += 2;
00230 INSIST(i + len <= nsecstruct.len);
00231 if (window * 256 > type)
00232 break;
00233 if ((window + 1) * 256 <= type)
00234 continue;
00235 if (type < (window * 256) + len * 8)
00236 present = ISC_TF(dns_nsec_isset(&nsecstruct.typebits[i],
00237 type % 256));
00238 break;
00239 }
00240 dns_rdata_freestruct(&nsecstruct);
00241 return (present);
00242 }
00243
00244 isc_result_t
00245 dns_nsec_nseconly(dns_db_t *db, dns_dbversion_t *version,
00246 isc_boolean_t *answer)
00247 {
00248 dns_dbnode_t *node = NULL;
00249 dns_rdataset_t rdataset;
00250 dns_rdata_dnskey_t dnskey;
00251 isc_result_t result;
00252
00253 REQUIRE(answer != NULL);
00254
00255 dns_rdataset_init(&rdataset);
00256
00257 result = dns_db_getoriginnode(db, &node);
00258 if (result != ISC_R_SUCCESS)
00259 return (result);
00260
00261 result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
00262 0, 0, &rdataset, NULL);
00263 dns_db_detachnode(db, &node);
00264
00265 if (result == ISC_R_NOTFOUND)
00266 *answer = ISC_FALSE;
00267 if (result != ISC_R_SUCCESS)
00268 return (result);
00269 for (result = dns_rdataset_first(&rdataset);
00270 result == ISC_R_SUCCESS;
00271 result = dns_rdataset_next(&rdataset)) {
00272 dns_rdata_t rdata = DNS_RDATA_INIT;
00273
00274 dns_rdataset_current(&rdataset, &rdata);
00275 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
00276 RUNTIME_CHECK(result == ISC_R_SUCCESS);
00277
00278 if (dnskey.algorithm == DST_ALG_RSAMD5 ||
00279 dnskey.algorithm == DST_ALG_RSASHA1 ||
00280 dnskey.algorithm == DST_ALG_DSA ||
00281 dnskey.algorithm == DST_ALG_ECC)
00282 break;
00283 }
00284 dns_rdataset_disassociate(&rdataset);
00285 if (result == ISC_R_SUCCESS)
00286 *answer = ISC_TRUE;
00287 if (result == ISC_R_NOMORE) {
00288 *answer = ISC_FALSE;
00289 result = ISC_R_SUCCESS;
00290 }
00291 return (result);
00292 }
00293
00294
00295
00296
00297
00298
00299
00300
00301 isc_result_t
00302 dns_nsec_noexistnodata(dns_rdatatype_t type, dns_name_t *name,
00303 dns_name_t *nsecname, dns_rdataset_t *nsecset,
00304 isc_boolean_t *exists, isc_boolean_t *data,
00305 dns_name_t *wild, dns_nseclog_t logit, void *arg)
00306 {
00307 int order;
00308 dns_rdata_t rdata = DNS_RDATA_INIT;
00309 isc_result_t result;
00310 dns_namereln_t relation;
00311 unsigned int olabels, nlabels, labels;
00312 dns_rdata_nsec_t nsec;
00313 isc_boolean_t atparent;
00314 isc_boolean_t ns;
00315 isc_boolean_t soa;
00316
00317 REQUIRE(exists != NULL);
00318 REQUIRE(data != NULL);
00319 REQUIRE(nsecset != NULL &&
00320 nsecset->type == dns_rdatatype_nsec);
00321
00322 result = dns_rdataset_first(nsecset);
00323 if (result != ISC_R_SUCCESS) {
00324 (*logit)(arg, ISC_LOG_DEBUG(3), "failure processing NSEC set");
00325 return (result);
00326 }
00327 dns_rdataset_current(nsecset, &rdata);
00328
00329 (*logit)(arg, ISC_LOG_DEBUG(3), "looking for relevant NSEC");
00330 relation = dns_name_fullcompare(name, nsecname, &order, &olabels);
00331
00332 if (order < 0) {
00333
00334
00335
00336 (*logit)(arg, ISC_LOG_DEBUG(3),
00337 "NSEC does not cover name, before NSEC");
00338 return (ISC_R_IGNORE);
00339 }
00340
00341 if (order == 0) {
00342
00343
00344
00345
00346 atparent = (olabels != 1) && dns_rdatatype_atparent(type);
00347 ns = dns_nsec_typepresent(&rdata, dns_rdatatype_ns);
00348 soa = dns_nsec_typepresent(&rdata, dns_rdatatype_soa);
00349 if (ns && !soa) {
00350 if (!atparent) {
00351
00352
00353
00354
00355
00356 (*logit)(arg, ISC_LOG_DEBUG(3),
00357 "ignoring parent nsec");
00358 return (ISC_R_IGNORE);
00359 }
00360 } else if (atparent && ns && soa) {
00361
00362
00363
00364
00365 (*logit)(arg, ISC_LOG_DEBUG(3),
00366 "ignoring child nsec");
00367 return (ISC_R_IGNORE);
00368 }
00369 if (type == dns_rdatatype_cname || type == dns_rdatatype_nxt ||
00370 type == dns_rdatatype_nsec || type == dns_rdatatype_key ||
00371 !dns_nsec_typepresent(&rdata, dns_rdatatype_cname)) {
00372 *exists = ISC_TRUE;
00373 *data = dns_nsec_typepresent(&rdata, type);
00374 (*logit)(arg, ISC_LOG_DEBUG(3),
00375 "nsec proves name exists (owner) data=%d",
00376 *data);
00377 return (ISC_R_SUCCESS);
00378 }
00379 (*logit)(arg, ISC_LOG_DEBUG(3), "NSEC proves CNAME exists");
00380 return (ISC_R_IGNORE);
00381 }
00382
00383 if (relation == dns_namereln_subdomain &&
00384 dns_nsec_typepresent(&rdata, dns_rdatatype_ns) &&
00385 !dns_nsec_typepresent(&rdata, dns_rdatatype_soa))
00386 {
00387
00388
00389
00390
00391
00392 (*logit)(arg, ISC_LOG_DEBUG(3), "ignoring parent nsec");
00393 return (ISC_R_IGNORE);
00394 }
00395
00396 result = dns_rdata_tostruct(&rdata, &nsec, NULL);
00397 if (result != ISC_R_SUCCESS)
00398 return (result);
00399 relation = dns_name_fullcompare(&nsec.next, name, &order, &nlabels);
00400 if (order == 0) {
00401 dns_rdata_freestruct(&nsec);
00402 (*logit)(arg, ISC_LOG_DEBUG(3),
00403 "ignoring nsec matches next name");
00404 return (ISC_R_IGNORE);
00405 }
00406
00407 if (order < 0 && !dns_name_issubdomain(nsecname, &nsec.next)) {
00408
00409
00410
00411 dns_rdata_freestruct(&nsec);
00412 (*logit)(arg, ISC_LOG_DEBUG(3),
00413 "ignoring nsec because name is past end of range");
00414 return (ISC_R_IGNORE);
00415 }
00416
00417 if (order > 0 && relation == dns_namereln_subdomain) {
00418 (*logit)(arg, ISC_LOG_DEBUG(3),
00419 "nsec proves name exist (empty)");
00420 dns_rdata_freestruct(&nsec);
00421 *exists = ISC_TRUE;
00422 *data = ISC_FALSE;
00423 return (ISC_R_SUCCESS);
00424 }
00425 if (wild != NULL) {
00426 dns_name_t common;
00427 dns_name_init(&common, NULL);
00428 if (olabels > nlabels) {
00429 labels = dns_name_countlabels(nsecname);
00430 dns_name_getlabelsequence(nsecname, labels - olabels,
00431 olabels, &common);
00432 } else {
00433 labels = dns_name_countlabels(&nsec.next);
00434 dns_name_getlabelsequence(&nsec.next, labels - nlabels,
00435 nlabels, &common);
00436 }
00437 result = dns_name_concatenate(dns_wildcardname, &common,
00438 wild, NULL);
00439 if (result != ISC_R_SUCCESS) {
00440 dns_rdata_freestruct(&nsec);
00441 (*logit)(arg, ISC_LOG_DEBUG(3),
00442 "failure generating wildcard name");
00443 return (result);
00444 }
00445 }
00446 dns_rdata_freestruct(&nsec);
00447 (*logit)(arg, ISC_LOG_DEBUG(3), "nsec range ok");
00448 *exists = ISC_FALSE;
00449 return (ISC_R_SUCCESS);
00450 }