LCOV - code coverage report
Current view: top level - source4/dsdb/kcc - scavenge_dns_records.c (source / functions) Hit Total Coverage
Test: coverage report for vadcx-master-patch-75612 fe003de8 Lines: 137 218 62.8 %
Date: 2024-02-29 22:57:05 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    DNS tombstoning routines
       5             : 
       6             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2018
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : 
      21             : */
      22             : 
      23             : #include "includes.h"
      24             : #include <ldb_errors.h>
      25             : #include "../lib/util/dlinklist.h"
      26             : #include "librpc/gen_ndr/ndr_misc.h"
      27             : #include "librpc/gen_ndr/ndr_drsuapi.h"
      28             : #include "librpc/gen_ndr/ndr_drsblobs.h"
      29             : #include "param/param.h"
      30             : #include "lib/util/dlinklist.h"
      31             : #include "ldb.h"
      32             : #include "dsdb/kcc/scavenge_dns_records.h"
      33             : #include "lib/ldb-samba/ldb_matching_rules.h"
      34             : #include "lib/util/time.h"
      35             : #include "dns_server/dnsserver_common.h"
      36             : #include "librpc/gen_ndr/ndr_dnsp.h"
      37             : #include "param/param.h"
      38             : 
      39             : #include "librpc/gen_ndr/ndr_misc.h"
      40             : #include "librpc/gen_ndr/ndr_drsuapi.h"
      41             : #include "librpc/gen_ndr/ndr_drsblobs.h"
      42             : 
      43             : /*
      44             :  * Copy only non-expired dns records from one message element to another.
      45             :  */
      46          12 : static NTSTATUS copy_current_records(TALLOC_CTX *mem_ctx,
      47             :                                      struct ldb_message_element *old_el,
      48             :                                      struct ldb_message_element *el,
      49             :                                      uint32_t dns_timestamp)
      50             : {
      51           0 :         unsigned int i;
      52           0 :         struct dnsp_DnssrvRpcRecord rec;
      53           0 :         enum ndr_err_code ndr_err;
      54             : 
      55          12 :         el->values = talloc_zero_array(mem_ctx, struct ldb_val,
      56             :                                        old_el->num_values);
      57          12 :         if (el->values == NULL) {
      58           0 :                 return NT_STATUS_NO_MEMORY;
      59             :         }
      60             : 
      61          30 :         for (i = 0; i < old_el->num_values; i++) {
      62          18 :                 ndr_err = ndr_pull_struct_blob(
      63          18 :                     &(old_el->values[i]),
      64             :                     mem_ctx,
      65             :                     &rec,
      66             :                     (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
      67          18 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
      68           0 :                         DBG_ERR("Failed to pull dns rec blob.\n");
      69           0 :                         return NT_STATUS_INTERNAL_ERROR;
      70             :                 }
      71          18 :                 if (rec.dwTimeStamp > dns_timestamp ||
      72          12 :                     rec.dwTimeStamp == 0) {
      73           6 :                         el->values[el->num_values] = old_el->values[i];
      74           6 :                         el->num_values++;
      75             :                 }
      76             :         }
      77             : 
      78          12 :         return NT_STATUS_OK;
      79             : }
      80             : 
      81             : /*
      82             :  * Check all records in a zone and tombstone them if they're expired.
      83             :  */
      84          18 : static NTSTATUS dns_tombstone_records_zone(TALLOC_CTX *mem_ctx,
      85             :                                            struct ldb_context *samdb,
      86             :                                            struct dns_server_zone *zone,
      87             :                                            uint32_t dns_timestamp,
      88             :                                            NTTIME entombed_time,
      89             :                                            char **error_string)
      90             : {
      91           0 :         WERROR werr;
      92           0 :         NTSTATUS status;
      93           0 :         unsigned int i;
      94          18 :         struct dnsserver_zoneinfo *zi = NULL;
      95          18 :         struct ldb_result *res = NULL;
      96          18 :         struct ldb_message_element *el = NULL;
      97          18 :         struct ldb_message_element *tombstone_el = NULL;
      98          18 :         struct ldb_message_element *old_el = NULL;
      99          18 :         struct ldb_message *new_msg = NULL;
     100           0 :         enum ndr_err_code ndr_err;
     101           0 :         int ret;
     102           0 :         struct GUID guid;
     103           0 :         struct GUID_txt_buf buf_guid;
     104          18 :         const char *attrs[] = {"dnsRecord",
     105             :                                "dNSTombstoned",
     106             :                                "objectGUID",
     107             :                                NULL};
     108             : 
     109          18 :         struct ldb_val true_val = {
     110             :                 .data = discard_const_p(uint8_t, "TRUE"),
     111             :                 .length = 4
     112             :         };
     113             : 
     114           0 :         struct ldb_val tombstone_blob;
     115          18 :         struct dnsp_DnssrvRpcRecord tombstone_struct = {
     116             :                 .wType = DNS_TYPE_TOMBSTONE,
     117             :                 .data = {.EntombedTime = entombed_time}
     118             :         };
     119             : 
     120          18 :         ndr_err = ndr_push_struct_blob(
     121             :             &tombstone_blob,
     122             :             mem_ctx,
     123             :             &tombstone_struct,
     124             :             (ndr_push_flags_fn_t)ndr_push_dnsp_DnssrvRpcRecord);
     125          18 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     126           0 :                 *error_string = discard_const_p(char,
     127             :                                                 "Failed to push TOMBSTONE"
     128             :                                                 "dnsp_DnssrvRpcRecord\n");
     129           0 :                 return NT_STATUS_INTERNAL_ERROR;
     130             :         }
     131             : 
     132          18 :         *error_string = NULL;
     133             : 
     134             :         /* Get NoRefreshInterval and RefreshInterval from zone properties.*/
     135          18 :         zi = talloc(mem_ctx, struct dnsserver_zoneinfo);
     136          18 :         if (zi == NULL) {
     137           0 :                 return NT_STATUS_NO_MEMORY;
     138             :         }
     139          18 :         werr = dns_get_zone_properties(samdb, mem_ctx, zone->dn, zi);
     140          18 :         if (W_ERROR_EQUAL(DNS_ERR(NOTZONE), werr)) {
     141           6 :                 return NT_STATUS_PROPSET_NOT_FOUND;
     142          12 :         } else if (!W_ERROR_IS_OK(werr)) {
     143           0 :                 return NT_STATUS_INTERNAL_ERROR;
     144             :         }
     145             : 
     146             :         /* Subtract them from current time to get the earliest possible.
     147             :          * timestamp allowed for a non-expired DNS record. */
     148          12 :         dns_timestamp -= zi->dwNoRefreshInterval + zi->dwRefreshInterval;
     149             : 
     150             :         /* Custom match gets dns records in the zone with dwTimeStamp < t. */
     151          12 :         ret = ldb_search(samdb,
     152             :                          mem_ctx,
     153             :                          &res,
     154             :                          zone->dn,
     155             :                          LDB_SCOPE_SUBTREE,
     156             :                          attrs,
     157             :                          "(&(objectClass=dnsNode)"
     158             :                          "(&(!(dnsTombstoned=TRUE))"
     159             :                          "(dnsRecord:" DSDB_MATCH_FOR_DNS_TO_TOMBSTONE_TIME
     160             :                          ":=%"PRIu32")))",
     161             :                          dns_timestamp);
     162          12 :         if (ret != LDB_SUCCESS) {
     163           0 :                 *error_string = talloc_asprintf(mem_ctx,
     164             :                                                 "Failed to search for dns "
     165             :                                                 "objects in zone %s: %s",
     166             :                                                 ldb_dn_get_linearized(zone->dn),
     167             :                                                 ldb_errstring(samdb));
     168           0 :                 return NT_STATUS_INTERNAL_ERROR;
     169             :         }
     170             : 
     171             :         /*
     172             :          * Do a constrained update on each expired DNS node. To do a constrained
     173             :          * update we leave the dnsRecord element as is, and just change the flag
     174             :          * to MOD_DELETE, then add a new element with the changes we want.  LDB
     175             :          * will run the deletion first, and bail out if a binary comparison
     176             :          * between the attribute we pass and the one in the database shows a
     177             :          * change.  This prevents race conditions.
     178             :          */
     179          24 :         for (i = 0; i < res->count; i++) {
     180          12 :                 new_msg = ldb_msg_copy(mem_ctx, res->msgs[i]);
     181          12 :                 if (new_msg == NULL) {
     182           0 :                         return NT_STATUS_INTERNAL_ERROR;
     183             :                 }
     184             : 
     185          12 :                 old_el = ldb_msg_find_element(new_msg, "dnsRecord");
     186          12 :                 if (old_el == NULL) {
     187           0 :                         TALLOC_FREE(new_msg);
     188           0 :                         return NT_STATUS_INTERNAL_ERROR;
     189             :                 }
     190          12 :                 old_el->flags = LDB_FLAG_MOD_DELETE;
     191             : 
     192          12 :                 ret = ldb_msg_add_empty(
     193             :                     new_msg, "dnsRecord", LDB_FLAG_MOD_ADD, &el);
     194          12 :                 if (ret != LDB_SUCCESS) {
     195           0 :                         TALLOC_FREE(new_msg);
     196           0 :                         return NT_STATUS_INTERNAL_ERROR;
     197             :                 }
     198             : 
     199          12 :                 status = copy_current_records(new_msg, old_el, el, dns_timestamp);
     200             : 
     201          12 :                 if (!NT_STATUS_IS_OK(status)) {
     202           0 :                         TALLOC_FREE(new_msg);
     203           0 :                         return NT_STATUS_INTERNAL_ERROR;
     204             :                 }
     205             : 
     206             :                 /* If nothing was expired, do nothing. */
     207          12 :                 if (el->num_values == old_el->num_values &&
     208           0 :                     el->num_values != 0) {
     209           0 :                         TALLOC_FREE(new_msg);
     210           0 :                         continue;
     211             :                 }
     212             : 
     213             :                 /*
     214             :                  * If everything was expired, we tombstone the node, which
     215             :                  * involves adding a tombstone dnsRecord and a 'dnsTombstoned:
     216             :                  * TRUE' attribute. That is, we want to end up with this:
     217             :                  *
     218             :                  *  objectClass: dnsNode
     219             :                  *  dnsRecord:  { .wType = DNSTYPE_TOMBSTONE,
     220             :                  *                .data.EntombedTime = <now> }
     221             :                  *  dnsTombstoned: TRUE
     222             :                  *
     223             :                  * and no other dnsRecords.
     224             :                  */
     225          12 :                 if (el->num_values == 0) {
     226           8 :                         struct ldb_val *vals = talloc_realloc(new_msg->elements,
     227             :                                                               el->values,
     228             :                                                               struct ldb_val,
     229             :                                                               1);
     230           8 :                         if (!vals) {
     231           0 :                                 TALLOC_FREE(new_msg);
     232           0 :                                 return NT_STATUS_INTERNAL_ERROR;
     233             :                         }
     234           8 :                         el->values = vals;
     235           8 :                         el->values[0] = tombstone_blob;
     236           8 :                         el->num_values = 1;
     237             : 
     238           8 :                         tombstone_el = ldb_msg_find_element(new_msg,
     239             :                                                   "dnsTombstoned");
     240             : 
     241           8 :                         if (tombstone_el == NULL) {
     242           4 :                                 ret = ldb_msg_add_value(new_msg,
     243             :                                                         "dnsTombstoned",
     244             :                                                         &true_val,
     245             :                                                         &tombstone_el);
     246           4 :                                 if (ret != LDB_SUCCESS) {
     247           0 :                                         TALLOC_FREE(new_msg);
     248           0 :                                         return NT_STATUS_INTERNAL_ERROR;
     249             :                                 }
     250           4 :                                 tombstone_el->flags = LDB_FLAG_MOD_ADD;
     251             :                         } else {
     252           4 :                                 if (tombstone_el->num_values != 1) {
     253           0 :                                         vals = talloc_realloc(
     254             :                                                 new_msg->elements,
     255             :                                                 tombstone_el->values,
     256             :                                                 struct ldb_val,
     257             :                                                 1);
     258           0 :                                         if (!vals) {
     259           0 :                                                 TALLOC_FREE(new_msg);
     260           0 :                                                 return NT_STATUS_INTERNAL_ERROR;
     261             :                                         }
     262           0 :                                         tombstone_el->values = vals;
     263           0 :                                         tombstone_el->num_values = 1;
     264             :                                 }
     265           4 :                                 tombstone_el->flags = LDB_FLAG_MOD_REPLACE;
     266           4 :                                 tombstone_el->values[0] = true_val;
     267             :                         }
     268             :                 } else {
     269             :                         /*
     270             :                          * Do not change the status of dnsTombstoned if we
     271             :                          * found any live records. If it exists, its value
     272             :                          * will be the harmless "FALSE", which is what we end
     273             :                          * up with when a tombstoned record is untombstoned.
     274             :                          * (in dns_common_replace).
     275             :                          */
     276           4 :                         ldb_msg_remove_attr(new_msg,
     277             :                                             "dnsTombstoned");
     278             :                 }
     279             : 
     280             :                 /* Set DN to the GUID in case the object was moved. */
     281          12 :                 el = ldb_msg_find_element(new_msg, "objectGUID");
     282          12 :                 if (el == NULL) {
     283           0 :                         TALLOC_FREE(new_msg);
     284           0 :                         *error_string =
     285           0 :                             talloc_asprintf(mem_ctx,
     286             :                                             "record has no objectGUID "
     287             :                                             "in zone %s",
     288             :                                             ldb_dn_get_linearized(zone->dn));
     289           0 :                         return NT_STATUS_INTERNAL_ERROR;
     290             :                 }
     291             : 
     292          12 :                 status = GUID_from_ndr_blob(el->values, &guid);
     293          12 :                 if (!NT_STATUS_IS_OK(status)) {
     294           0 :                         TALLOC_FREE(new_msg);
     295           0 :                         *error_string =
     296             :                             discard_const_p(char, "Error: Invalid GUID.\n");
     297           0 :                         return NT_STATUS_INTERNAL_ERROR;
     298             :                 }
     299             : 
     300          12 :                 GUID_buf_string(&guid, &buf_guid);
     301          12 :                 new_msg->dn =
     302          12 :                     ldb_dn_new_fmt(mem_ctx, samdb, "<GUID=%s>", buf_guid.buf);
     303             : 
     304             :                 /* Remove the GUID so we're not trying to modify it. */
     305          12 :                 ldb_msg_remove_attr(new_msg, "objectGUID");
     306             : 
     307          12 :                 ret = ldb_modify(samdb, new_msg);
     308          12 :                 if (ret != LDB_SUCCESS) {
     309           0 :                         TALLOC_FREE(new_msg);
     310           0 :                         *error_string =
     311           0 :                             talloc_asprintf(mem_ctx,
     312             :                                             "Failed to modify dns record "
     313             :                                             "in zone %s: %s",
     314             :                                             ldb_dn_get_linearized(zone->dn),
     315             :                                             ldb_errstring(samdb));
     316           0 :                         return NT_STATUS_INTERNAL_ERROR;
     317             :                 }
     318          12 :                 TALLOC_FREE(new_msg);
     319             :         }
     320             : 
     321          12 :         return NT_STATUS_OK;
     322             : }
     323             : 
     324             : /*
     325             :  * Tombstone all expired DNS records.
     326             :  */
     327           6 : NTSTATUS dns_tombstone_records(TALLOC_CTX *mem_ctx,
     328             :                                struct ldb_context *samdb,
     329             :                                char **error_string)
     330             : {
     331           6 :         struct dns_server_zone *zones = NULL;
     332           6 :         struct dns_server_zone *z = NULL;
     333           0 :         NTSTATUS ret;
     334           0 :         uint32_t dns_timestamp;
     335           0 :         NTTIME entombed_time;
     336           6 :         TALLOC_CTX *tmp_ctx = NULL;
     337           6 :         time_t unix_now = time(NULL);
     338             : 
     339           6 :         unix_to_nt_time(&entombed_time, unix_now);
     340           6 :         dns_timestamp = unix_to_dns_timestamp(unix_now);
     341             : 
     342           6 :         tmp_ctx = talloc_new(mem_ctx);
     343           6 :         if (tmp_ctx == NULL) {
     344           0 :                 return NT_STATUS_NO_MEMORY;
     345             :         }
     346             : 
     347           6 :         ret = dns_common_zones(samdb, tmp_ctx, NULL, &zones);
     348           6 :         if (!NT_STATUS_IS_OK(ret)) {
     349           0 :                 TALLOC_FREE(tmp_ctx);
     350           0 :                 return ret;
     351             :         }
     352             : 
     353          24 :         for (z = zones; z; z = z->next) {
     354          18 :                 ret = dns_tombstone_records_zone(tmp_ctx,
     355             :                                                  samdb,
     356             :                                                  z,
     357             :                                                  dns_timestamp,
     358             :                                                  entombed_time,
     359             :                                                  error_string);
     360          18 :                 if (NT_STATUS_EQUAL(ret, NT_STATUS_PROPSET_NOT_FOUND)) {
     361           6 :                         continue;
     362          12 :                 } else if (!NT_STATUS_IS_OK(ret)) {
     363           0 :                         TALLOC_FREE(tmp_ctx);
     364           0 :                         return ret;
     365             :                 }
     366             :         }
     367           6 :         TALLOC_FREE(tmp_ctx);
     368           6 :         return NT_STATUS_OK;
     369             : }
     370             : 
     371             : /*
     372             :  * Delete all DNS tombstones that have been around for longer than the server
     373             :  * property 'dns_tombstone_interval' which we store in smb.conf, which
     374             :  * corresponds to DsTombstoneInterval in [MS-DNSP] 3.1.1.1.1 "DNS Server
     375             :  * Integer Properties".
     376             :  */
     377          66 : NTSTATUS dns_delete_tombstones(TALLOC_CTX *mem_ctx,
     378             :                                struct ldb_context *samdb,
     379             :                                char **error_string)
     380             : {
     381          66 :         struct dns_server_zone *zones = NULL;
     382          66 :         struct dns_server_zone *z = NULL;
     383           2 :         int ret, i;
     384           2 :         NTSTATUS status;
     385           2 :         uint32_t current_time;
     386           2 :         uint32_t tombstone_interval;
     387           2 :         uint32_t tombstone_hours;
     388           2 :         NTTIME tombstone_nttime;
     389           2 :         enum ndr_err_code ndr_err;
     390          66 :         struct ldb_result *res = NULL;
     391          66 :         TALLOC_CTX *tmp_ctx = NULL;
     392          66 :         struct loadparm_context *lp_ctx = NULL;
     393          66 :         struct ldb_message_element *el = NULL;
     394          66 :         struct dnsp_DnssrvRpcRecord rec = {0};
     395          66 :         const char *attrs[] = {"dnsRecord", "dNSTombstoned", NULL};
     396             : 
     397          66 :         current_time = unix_to_dns_timestamp(time(NULL));
     398             : 
     399          66 :         lp_ctx = (struct loadparm_context *)ldb_get_opaque(samdb, "loadparm");
     400          66 :         tombstone_interval = lpcfg_parm_ulong(lp_ctx, NULL,
     401             :                                               "dnsserver",
     402             :                                               "dns_tombstone_interval",
     403             :                                               24 * 14);
     404             : 
     405          66 :         tombstone_hours = current_time - tombstone_interval;
     406          66 :         status = dns_timestamp_to_nt_time(&tombstone_nttime,
     407             :                                           tombstone_hours);
     408             : 
     409          66 :         if (!NT_STATUS_IS_OK(status)) {
     410           0 :                 DBG_ERR("DNS timestamp exceeds NTTIME epoch.\n");
     411           0 :                 return NT_STATUS_INTERNAL_ERROR;
     412             :         }
     413             : 
     414          66 :         tmp_ctx = talloc_new(mem_ctx);
     415          66 :         if (tmp_ctx == NULL) {
     416           0 :                 return NT_STATUS_NO_MEMORY;
     417             :         }
     418          66 :         status = dns_common_zones(samdb, tmp_ctx, NULL, &zones);
     419          66 :         if (!NT_STATUS_IS_OK(status)) {
     420           0 :                 TALLOC_FREE(tmp_ctx);
     421           0 :                 return status;
     422             :         }
     423             : 
     424         202 :         for (z = zones; z; z = z->next) {
     425             :                 /*
     426             :                  * This can load a very large set, but on the
     427             :                  * assumption that the number of tombstones is
     428             :                  * relatively small compared with the number of active
     429             :                  * records, and that this is an indexed lookup, this
     430             :                  * should be OK.  We can make a match rule if
     431             :                  * returning the set of tombstones becomes an issue.
     432             :                  */
     433             : 
     434         136 :                 ret = ldb_search(samdb,
     435             :                                  tmp_ctx,
     436             :                                  &res,
     437             :                                  z->dn,
     438             :                                  LDB_SCOPE_SUBTREE,
     439             :                                  attrs,
     440             :                                  "(&(objectClass=dnsNode)(dNSTombstoned=TRUE))");
     441             : 
     442         136 :                 if (ret != LDB_SUCCESS) {
     443           0 :                         *error_string =
     444           0 :                             talloc_asprintf(mem_ctx,
     445             :                                             "Failed to "
     446             :                                             "search for tombstoned "
     447             :                                             "dns objects in zone %s: %s",
     448             :                                             ldb_dn_get_linearized(z->dn),
     449             :                                             ldb_errstring(samdb));
     450           0 :                         TALLOC_FREE(tmp_ctx);
     451           0 :                         return NT_STATUS_INTERNAL_ERROR;
     452             :                 }
     453             : 
     454         214 :                 for (i = 0; i < res->count; i++) {
     455          78 :                         struct ldb_message *msg = res->msgs[i];
     456          78 :                         el = ldb_msg_find_element(msg, "dnsRecord");
     457          78 :                         if (el == NULL) {
     458           0 :                                 DBG_ERR("The tombstoned dns node %s has no dns "
     459             :                                         "records, which should not happen.\n",
     460             :                                         ldb_dn_get_linearized(msg->dn)
     461             :                                         );
     462           0 :                                 continue;
     463             :                         }
     464             :                         /*
     465             :                          * Below we assume the element has one value, which we
     466             :                          * expect because when we tombstone a node we remove
     467             :                          * all the records except for the tombstone.
     468             :                          */
     469          78 :                         if (el->num_values != 1) {
     470           0 :                                 DBG_ERR("The tombstoned dns node %s has %u "
     471             :                                         "dns records, expected one.\n",
     472             :                                         ldb_dn_get_linearized(msg->dn),
     473             :                                         el->num_values
     474             :                                         );
     475           0 :                                 continue;
     476             :                         }
     477             : 
     478          78 :                         ndr_err = ndr_pull_struct_blob(
     479          78 :                             el->values,
     480             :                             tmp_ctx,
     481             :                             &rec,
     482             :                             (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
     483          78 :                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     484           0 :                                 TALLOC_FREE(tmp_ctx);
     485           0 :                                 DBG_ERR("Failed to pull dns rec blob.\n");
     486           0 :                                 return NT_STATUS_INTERNAL_ERROR;
     487             :                         }
     488             : 
     489          78 :                         if (rec.wType != DNS_TYPE_TOMBSTONE) {
     490           0 :                                 DBG_ERR("A tombstoned dnsNode has non-tombstoned"
     491             :                                         " records, which should not happen.\n");
     492           0 :                                 continue;
     493             :                         }
     494             : 
     495          78 :                         if (rec.data.EntombedTime > tombstone_nttime) {
     496          58 :                                 continue;
     497             :                         }
     498             :                         /*
     499             :                          * Between 4.9 and 4.14 in some places we saved the
     500             :                          * tombstone time as hours since the start of 1601,
     501             :                          * not in NTTIME ten-millionths of a second units.
     502             :                          *
     503             :                          * We can accommodate these bad values by noting that
     504             :                          * all the realistic timestamps in that measurement
     505             :                          * fall within the first *second* of NTTIME, that is,
     506             :                          * before 1601-01-01 00:00:01; and that these
     507             :                          * timestamps are not realistic for NTTIME timestamps.
     508             :                          *
     509             :                          * Calculation: there are roughly 365.25 * 24 = 8766
     510             :                          * hours per year, and < 500 years since 1601, so
     511             :                          * 4383000 would be a fine threshold. We round up to
     512             :                          * the crore-second (c. 2741CE) in honour of NTTIME.
     513             :                          */
     514          20 :                         if ((rec.data.EntombedTime < 10000000) &&
     515           8 :                             (rec.data.EntombedTime > tombstone_hours)) {
     516           4 :                                 continue;
     517             :                         }
     518             : 
     519          16 :                         ret = dsdb_delete(samdb, msg->dn, 0);
     520          16 :                         if (ret != LDB_ERR_NO_SUCH_OBJECT &&
     521           0 :                             ret != LDB_SUCCESS) {
     522           0 :                                 TALLOC_FREE(tmp_ctx);
     523           0 :                                 DBG_ERR("Failed to delete dns node \n");
     524           0 :                                 return NT_STATUS_INTERNAL_ERROR;
     525             :                         }
     526             :                 }
     527             : 
     528             :         }
     529          66 :         TALLOC_FREE(tmp_ctx);
     530          66 :         return NT_STATUS_OK;
     531             : }

Generated by: LCOV version 1.14