LCOV - code coverage report
Current view: top level - source4/dns_server - dns_update.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 304 459 66.2 %
Date: 2024-04-21 15:09:00 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    DNS server handler for update requests
       5             : 
       6             :    Copyright (C) 2010 Kai Blin  <kai@samba.org>
       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             : #include "includes.h"
      23             : #include "libcli/util/ntstatus.h"
      24             : #include "librpc/ndr/libndr.h"
      25             : #include "librpc/gen_ndr/ndr_dns.h"
      26             : #include "librpc/gen_ndr/ndr_dnsp.h"
      27             : #include <ldb.h>
      28             : #include "param/param.h"
      29             : #include "param/loadparm.h"
      30             : #include "dsdb/samdb/samdb.h"
      31             : #include "dsdb/common/util.h"
      32             : #include "samba/service_task.h"
      33             : #include "dns_server/dns_server.h"
      34             : #include "auth/auth.h"
      35             : 
      36             : #undef DBGC_CLASS
      37             : #define DBGC_CLASS DBGC_DNS
      38             : 
      39             : static WERROR dns_rr_to_dnsp(TALLOC_CTX *mem_ctx,
      40             :                              const struct dns_res_rec *rrec,
      41             :                              struct dnsp_DnssrvRpcRecord *r,
      42             :                              bool name_is_static);
      43             : 
      44         238 : static WERROR check_one_prerequisite(struct dns_server *dns,
      45             :                                      TALLOC_CTX *mem_ctx,
      46             :                                      const struct dns_name_question *zone,
      47             :                                      const struct dns_res_rec *pr,
      48             :                                      bool *final_result)
      49             : {
      50           0 :         bool match;
      51           0 :         WERROR werror;
      52           0 :         struct ldb_dn *dn;
      53           0 :         uint16_t i;
      54         238 :         bool found = false;
      55         238 :         struct dnsp_DnssrvRpcRecord *rec = NULL;
      56           0 :         struct dnsp_DnssrvRpcRecord *ans;
      57           0 :         uint16_t a_count;
      58             : 
      59         238 :         size_t host_part_len = 0;
      60             : 
      61         238 :         *final_result = true;
      62             : 
      63         238 :         if (pr->ttl != 0) {
      64           4 :                 return DNS_ERR(FORMAT_ERROR);
      65             :         }
      66             : 
      67         234 :         match = dns_name_match(zone->name, pr->name, &host_part_len);
      68         234 :         if (!match) {
      69           6 :                 return DNS_ERR(NOTZONE);
      70             :         }
      71             : 
      72         228 :         werror = dns_name2dn(dns, mem_ctx, pr->name, &dn);
      73         228 :         W_ERROR_NOT_OK_RETURN(werror);
      74             : 
      75         228 :         if (pr->rr_class == DNS_QCLASS_ANY) {
      76             : 
      77           8 :                 if (pr->length != 0) {
      78           0 :                         return DNS_ERR(FORMAT_ERROR);
      79             :                 }
      80             : 
      81             : 
      82           8 :                 if (pr->rr_type == DNS_QTYPE_ALL) {
      83             :                         /*
      84             :                          */
      85           0 :                         werror = dns_lookup_records(dns, mem_ctx, dn, &ans, &a_count);
      86           0 :                         if (W_ERROR_EQUAL(werror, WERR_DNS_ERROR_NAME_DOES_NOT_EXIST)) {
      87           0 :                                 return DNS_ERR(NAME_ERROR);
      88             :                         }
      89           0 :                         W_ERROR_NOT_OK_RETURN(werror);
      90             : 
      91           0 :                         if (a_count == 0) {
      92           0 :                                 return DNS_ERR(NAME_ERROR);
      93             :                         }
      94             :                 } else {
      95             :                         /*
      96             :                          */
      97           8 :                         werror = dns_lookup_records(dns, mem_ctx, dn, &ans, &a_count);
      98           8 :                         if (W_ERROR_EQUAL(werror, WERR_DNS_ERROR_NAME_DOES_NOT_EXIST)) {
      99           4 :                                 return DNS_ERR(NXRRSET);
     100             :                         }
     101           4 :                         if (W_ERROR_EQUAL(werror, DNS_ERR(NAME_ERROR))) {
     102           0 :                                 return DNS_ERR(NXRRSET);
     103             :                         }
     104           4 :                         W_ERROR_NOT_OK_RETURN(werror);
     105             : 
     106          12 :                         for (i = 0; i < a_count; i++) {
     107           8 :                                 if (ans[i].wType == (enum dns_record_type) pr->rr_type) {
     108           0 :                                         found = true;
     109           0 :                                         break;
     110             :                                 }
     111             :                         }
     112           4 :                         if (!found) {
     113           4 :                                 return DNS_ERR(NXRRSET);
     114             :                         }
     115             :                 }
     116             : 
     117             :                 /*
     118             :                  * RFC2136 3.2.5 doesn't actually mention the need to return
     119             :                  * OK here, but otherwise we'd always return a FORMAT_ERROR
     120             :                  * later on. This also matches Microsoft DNS behavior.
     121             :                  */
     122           0 :                 return WERR_OK;
     123             :         }
     124             : 
     125         220 :         if (pr->rr_class == DNS_QCLASS_NONE) {
     126         166 :                 if (pr->length != 0) {
     127           0 :                         return DNS_ERR(FORMAT_ERROR);
     128             :                 }
     129             : 
     130         166 :                 if (pr->rr_type == DNS_QTYPE_ALL) {
     131             :                         /*
     132             :                          */
     133           0 :                         werror = dns_lookup_records(dns, mem_ctx, dn, &ans, &a_count);
     134           0 :                         if (W_ERROR_EQUAL(werror, WERR_OK)) {
     135           0 :                                 return DNS_ERR(YXDOMAIN);
     136             :                         }
     137             :                 } else {
     138             :                         /*
     139             :                          */
     140         166 :                         werror = dns_lookup_records(dns, mem_ctx, dn, &ans, &a_count);
     141         166 :                         if (W_ERROR_EQUAL(werror, WERR_DNS_ERROR_NAME_DOES_NOT_EXIST)) {
     142         110 :                                 werror = WERR_OK;
     143             :                         }
     144         166 :                         if (W_ERROR_EQUAL(werror, DNS_ERR(NAME_ERROR))) {
     145           0 :                                 werror = WERR_OK;
     146             :                         }
     147             : 
     148         238 :                         for (i = 0; i < a_count; i++) {
     149          72 :                                 if (ans[i].wType == (enum dns_record_type) pr->rr_type) {
     150           0 :                                         found = true;
     151           0 :                                         break;
     152             :                                 }
     153             :                         }
     154         166 :                         if (found) {
     155           0 :                                 return DNS_ERR(YXRRSET);
     156             :                         }
     157             :                 }
     158             : 
     159             :                 /*
     160             :                  * RFC2136 3.2.5 doesn't actually mention the need to return
     161             :                  * OK here, but otherwise we'd always return a FORMAT_ERROR
     162             :                  * later on. This also matches Microsoft DNS behavior.
     163             :                  */
     164         166 :                 return WERR_OK;
     165             :         }
     166             : 
     167          54 :         if (pr->rr_class != zone->question_class) {
     168           0 :                 return DNS_ERR(FORMAT_ERROR);
     169             :         }
     170             : 
     171          54 :         *final_result = false;
     172             : 
     173          54 :         werror = dns_lookup_records(dns, mem_ctx, dn, &ans, &a_count);
     174          54 :         if (W_ERROR_EQUAL(werror, WERR_DNS_ERROR_NAME_DOES_NOT_EXIST)) {
     175          46 :                 return DNS_ERR(NXRRSET);
     176             :         }
     177           8 :         if (W_ERROR_EQUAL(werror, DNS_ERR(NAME_ERROR))) {
     178           0 :                 return DNS_ERR(NXRRSET);
     179             :         }
     180           8 :         W_ERROR_NOT_OK_RETURN(werror);
     181             : 
     182           8 :         rec = talloc_zero(mem_ctx, struct dnsp_DnssrvRpcRecord);
     183           8 :         W_ERROR_HAVE_NO_MEMORY(rec);
     184             : 
     185           8 :         werror = dns_rr_to_dnsp(rec, pr, rec, dns_name_is_static(ans, a_count));
     186           8 :         W_ERROR_NOT_OK_RETURN(werror);
     187             : 
     188          12 :         for (i = 0; i < a_count; i++) {
     189          10 :                 if (dns_record_match(rec, &ans[i])) {
     190           6 :                         found = true;
     191           6 :                         break;
     192             :                 }
     193             :         }
     194             : 
     195           8 :         if (!found) {
     196           2 :                 return DNS_ERR(NXRRSET);
     197             :         }
     198             : 
     199           6 :         return WERR_OK;
     200             : }
     201             : 
     202        2491 : static WERROR check_prerequisites(struct dns_server *dns,
     203             :                                   TALLOC_CTX *mem_ctx,
     204             :                                   const struct dns_name_question *zone,
     205             :                                   const struct dns_res_rec *prereqs, uint16_t count)
     206             : {
     207           0 :         uint16_t i;
     208        2491 :         WERROR final_error = WERR_OK;
     209             : 
     210        2711 :         for (i = 0; i < count; i++) {
     211           0 :                 bool final;
     212           0 :                 WERROR werror;
     213             : 
     214         238 :                 werror = check_one_prerequisite(dns, mem_ctx, zone,
     215         238 :                                                 &prereqs[i], &final);
     216         238 :                 if (!W_ERROR_IS_OK(werror)) {
     217          66 :                         if (final) {
     218          18 :                                 return werror;
     219             :                         }
     220          48 :                         if (W_ERROR_IS_OK(final_error)) {
     221          28 :                                 final_error = werror;
     222             :                         }
     223             :                 }
     224             :         }
     225             : 
     226        2473 :         if (!W_ERROR_IS_OK(final_error)) {
     227          28 :                 return final_error;
     228             :         }
     229             : 
     230        2445 :         return WERR_OK;
     231             : }
     232             : 
     233        1168 : static WERROR update_prescan(const struct dns_name_question *zone,
     234             :                              const struct dns_res_rec *updates, uint16_t count)
     235             : {
     236           0 :         const struct dns_res_rec *r;
     237           0 :         uint16_t i;
     238           0 :         size_t host_part_len;
     239           0 :         bool match;
     240             : 
     241        2398 :         for (i = 0; i < count; i++) {
     242        1230 :                 r = &updates[i];
     243        1230 :                 match = dns_name_match(zone->name, r->name, &host_part_len);
     244        1230 :                 if (!match) {
     245           0 :                         return DNS_ERR(NOTZONE);
     246             :                 }
     247        1230 :                 if (zone->question_class == r->rr_class) {
     248        1053 :                         if (r->rr_type == DNS_QTYPE_ALL) {
     249           0 :                                 return DNS_ERR(FORMAT_ERROR);
     250             :                         }
     251        1053 :                         if (r->rr_type == DNS_QTYPE_AXFR) {
     252           0 :                                 return DNS_ERR(FORMAT_ERROR);
     253             :                         }
     254        1053 :                         if (r->rr_type == DNS_QTYPE_MAILB) {
     255           0 :                                 return DNS_ERR(FORMAT_ERROR);
     256             :                         }
     257        1053 :                         if (r->rr_type == DNS_QTYPE_MAILA) {
     258           0 :                                 return DNS_ERR(FORMAT_ERROR);
     259             :                         }
     260         177 :                 } else if (r->rr_class == DNS_QCLASS_ANY) {
     261          48 :                         if (r->ttl != 0) {
     262           0 :                                 return DNS_ERR(FORMAT_ERROR);
     263             :                         }
     264          48 :                         if (r->length != 0) {
     265           0 :                                 return DNS_ERR(FORMAT_ERROR);
     266             :                         }
     267          48 :                         if (r->rr_type == DNS_QTYPE_AXFR) {
     268           0 :                                 return DNS_ERR(FORMAT_ERROR);
     269             :                         }
     270          48 :                         if (r->rr_type == DNS_QTYPE_MAILB) {
     271           0 :                                 return DNS_ERR(FORMAT_ERROR);
     272             :                         }
     273          48 :                         if (r->rr_type == DNS_QTYPE_MAILA) {
     274           0 :                                 return DNS_ERR(FORMAT_ERROR);
     275             :                         }
     276         129 :                 } else if (r->rr_class == DNS_QCLASS_NONE) {
     277         129 :                         if (r->ttl != 0) {
     278           0 :                                 return DNS_ERR(FORMAT_ERROR);
     279             :                         }
     280         129 :                         if (r->rr_type == DNS_QTYPE_ALL) {
     281           0 :                                 return DNS_ERR(FORMAT_ERROR);
     282             :                         }
     283         129 :                         if (r->rr_type == DNS_QTYPE_AXFR) {
     284           0 :                                 return DNS_ERR(FORMAT_ERROR);
     285             :                         }
     286         129 :                         if (r->rr_type == DNS_QTYPE_MAILB) {
     287           0 :                                 return DNS_ERR(FORMAT_ERROR);
     288             :                         }
     289         129 :                         if (r->rr_type == DNS_QTYPE_MAILA) {
     290           0 :                                 return DNS_ERR(FORMAT_ERROR);
     291             :                         }
     292             :                 } else {
     293           0 :                         return DNS_ERR(FORMAT_ERROR);
     294             :                 }
     295             :         }
     296        1168 :         return WERR_OK;
     297             : }
     298             : 
     299        1188 : static WERROR dns_rr_to_dnsp(TALLOC_CTX *mem_ctx,
     300             :                              const struct dns_res_rec *rrec,
     301             :                              struct dnsp_DnssrvRpcRecord *r,
     302             :                              bool name_is_static)
     303             : {
     304           0 :         enum ndr_err_code ndr_err;
     305             : 
     306        1188 :         if (rrec->rr_type == DNS_QTYPE_ALL) {
     307           0 :                 return DNS_ERR(FORMAT_ERROR);
     308             :         }
     309             : 
     310        1188 :         ZERO_STRUCTP(r);
     311             : 
     312        1188 :         r->wType = (enum dns_record_type) rrec->rr_type;
     313        1188 :         r->dwTtlSeconds = rrec->ttl;
     314        1188 :         r->rank = DNS_RANK_ZONE;
     315        1188 :         if (name_is_static) {
     316         142 :                 r->dwTimeStamp = 0;
     317             :         } else {
     318        1046 :                 r->dwTimeStamp = unix_to_dns_timestamp(time(NULL));
     319             :         }
     320             : 
     321             :         /* If we get QCLASS_ANY, we're done here */
     322        1188 :         if (rrec->rr_class == DNS_QCLASS_ANY) {
     323           0 :                 goto done;
     324             :         }
     325             : 
     326        1188 :         switch(rrec->rr_type) {
     327         221 :         case DNS_QTYPE_A:
     328         221 :                 r->data.ipv4 = talloc_strdup(mem_ctx, rrec->rdata.ipv4_record);
     329         221 :                 W_ERROR_HAVE_NO_MEMORY(r->data.ipv4);
     330        1188 :                 break;
     331         111 :         case DNS_QTYPE_AAAA:
     332         111 :                 r->data.ipv6 = talloc_strdup(mem_ctx, rrec->rdata.ipv6_record);
     333         111 :                 W_ERROR_HAVE_NO_MEMORY(r->data.ipv6);
     334         111 :                 break;
     335           0 :         case DNS_QTYPE_NS:
     336           0 :                 r->data.ns = talloc_strdup(mem_ctx, rrec->rdata.ns_record);
     337           0 :                 W_ERROR_HAVE_NO_MEMORY(r->data.ns);
     338           0 :                 break;
     339          42 :         case DNS_QTYPE_CNAME:
     340          42 :                 r->data.cname = talloc_strdup(mem_ctx, rrec->rdata.cname_record);
     341          42 :                 W_ERROR_HAVE_NO_MEMORY(r->data.cname);
     342          42 :                 break;
     343          50 :         case DNS_QTYPE_SRV:
     344          50 :                 r->data.srv.wPriority = rrec->rdata.srv_record.priority;
     345          50 :                 r->data.srv.wWeight = rrec->rdata.srv_record.weight;
     346          50 :                 r->data.srv.wPort = rrec->rdata.srv_record.port;
     347         100 :                 r->data.srv.nameTarget = talloc_strdup(mem_ctx,
     348          50 :                                 rrec->rdata.srv_record.target);
     349          50 :                 W_ERROR_HAVE_NO_MEMORY(r->data.srv.nameTarget);
     350          50 :                 break;
     351           0 :         case DNS_QTYPE_PTR:
     352           0 :                 r->data.ptr = talloc_strdup(mem_ctx, rrec->rdata.ptr_record);
     353           0 :                 W_ERROR_HAVE_NO_MEMORY(r->data.ptr);
     354           0 :                 break;
     355           2 :         case DNS_QTYPE_MX:
     356           2 :                 r->data.mx.wPriority = rrec->rdata.mx_record.preference;
     357           4 :                 r->data.mx.nameTarget = talloc_strdup(mem_ctx,
     358           2 :                                 rrec->rdata.mx_record.exchange);
     359           2 :                 W_ERROR_HAVE_NO_MEMORY(r->data.mx.nameTarget);
     360           2 :                 break;
     361         762 :         case DNS_QTYPE_TXT:
     362         762 :                 ndr_err = ndr_dnsp_string_list_copy(mem_ctx,
     363             :                                                     &rrec->rdata.txt_record.txt,
     364             :                                                     &r->data.txt);
     365         762 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     366           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     367             :                 }
     368             : 
     369         762 :                 break;
     370           0 :         default:
     371           0 :                 DEBUG(0, ("Got a qytpe of %d\n", rrec->rr_type));
     372           0 :                 return DNS_ERR(NOT_IMPLEMENTED);
     373             :         }
     374             : 
     375        1188 : done:
     376             : 
     377        1188 :         return WERR_OK;
     378             : }
     379             : 
     380             : 
     381        1228 : static WERROR handle_one_update(struct dns_server *dns,
     382             :                                 TALLOC_CTX *mem_ctx,
     383             :                                 const struct dns_name_question *zone,
     384             :                                 const struct dns_res_rec *update,
     385             :                                 const struct dns_server_tkey *tkey)
     386             : {
     387        1228 :         struct dnsp_DnssrvRpcRecord *recs = NULL;
     388        1228 :         uint16_t rcount = 0;
     389           0 :         struct ldb_dn *dn;
     390           0 :         uint16_t i;
     391        1228 :         uint16_t first = 0;
     392           0 :         WERROR werror;
     393        1228 :         bool tombstoned = false;
     394        1228 :         bool needs_add = false;
     395           0 :         bool name_is_static;
     396             : 
     397        1228 :         DBG_NOTICE("Looking at record: \n");
     398        1228 :         if (DEBUGLVL(DBGLVL_NOTICE)) {
     399           0 :                 NDR_PRINT_DEBUG(dns_res_rec, discard_const(update));
     400             :         }
     401             : 
     402        1228 :         switch (update->rr_type) {
     403        1228 :         case DNS_QTYPE_A:
     404             :         case DNS_QTYPE_NS:
     405             :         case DNS_QTYPE_CNAME:
     406             :         case DNS_QTYPE_SOA:
     407             :         case DNS_QTYPE_PTR:
     408             :         case DNS_QTYPE_MX:
     409             :         case DNS_QTYPE_AAAA:
     410             :         case DNS_QTYPE_SRV:
     411             :         case DNS_QTYPE_TXT:
     412             :         case DNS_QTYPE_ALL:
     413        1228 :                 break;
     414           0 :         default:
     415           0 :                 DEBUG(0, ("Can't handle updates of type %u yet\n",
     416             :                           update->rr_type));
     417           0 :                 return DNS_ERR(NOT_IMPLEMENTED);
     418             :         }
     419             : 
     420        1228 :         werror = dns_name2dn(dns, mem_ctx, update->name, &dn);
     421        1228 :         DBG_DEBUG("dns_name2dn(): %s\n", win_errstr(werror));
     422        1228 :         W_ERROR_NOT_OK_RETURN(werror);
     423             : 
     424        1228 :         werror = dns_common_lookup(dns->samdb, mem_ctx, dn,
     425             :                                    &recs, &rcount, &tombstoned);
     426        1228 :         DBG_DEBUG("dns_common_lookup(): %s\n", win_errstr(werror));
     427        1228 :         if (W_ERROR_EQUAL(werror, WERR_DNS_ERROR_NAME_DOES_NOT_EXIST)) {
     428         318 :                 needs_add = true;
     429         318 :                 werror = WERR_OK;
     430             :         }
     431        1228 :         W_ERROR_NOT_OK_RETURN(werror);
     432             : 
     433        1228 :         if (tombstoned) {
     434             :                 /*
     435             :                  * we need to keep the existing tombstone record
     436             :                  * and ignore it.
     437             :                  *
     438             :                  * There *should* only be a single record of type TOMBSTONE,
     439             :                  * but we don't insist.
     440             :                  */
     441          22 :                 if (rcount != 1) {
     442           0 :                         DBG_WARNING("Tombstoned dnsNode has %u records, "
     443             :                                     "expected 1\n", rcount);
     444           0 :                         if (DEBUGLVL(DBGLVL_WARNING)) {
     445           0 :                                 NDR_PRINT_DEBUG(dns_res_rec, discard_const(update));
     446             :                         }
     447             :                 }
     448          22 :                 first = rcount;
     449             :         }
     450             : 
     451        1228 :         name_is_static = dns_name_is_static(recs, rcount);
     452             : 
     453        1228 :         if (update->rr_class == zone->question_class) {
     454        1051 :                 if (update->rr_type == DNS_QTYPE_CNAME) {
     455             :                         /*
     456             :                          * If there is a record in the directory
     457             :                          * that's not a CNAME, ignore update
     458             :                          */
     459          50 :                         for (i = first; i < rcount; i++) {
     460          10 :                                 if (recs[i].wType != DNS_TYPE_CNAME) {
     461           0 :                                         DEBUG(5, ("Skipping update\n"));
     462           0 :                                         return WERR_OK;
     463             :                                 }
     464             :                         }
     465             : 
     466             :                         /*
     467             :                          * There should be no entries besides one CNAME record
     468             :                          * per name, so replace everything with the new CNAME
     469             :                          */
     470             : 
     471          40 :                         rcount = first;
     472          40 :                         recs = talloc_realloc(mem_ctx, recs,
     473             :                                         struct dnsp_DnssrvRpcRecord, rcount + 1);
     474          40 :                         W_ERROR_HAVE_NO_MEMORY(recs);
     475             : 
     476          40 :                         werror = dns_rr_to_dnsp(
     477          40 :                             recs, update, &recs[rcount], name_is_static);
     478          40 :                         DBG_DEBUG("dns_rr_to_dnsp(CNAME): %s\n", win_errstr(werror));
     479          40 :                         W_ERROR_NOT_OK_RETURN(werror);
     480          40 :                         rcount += 1;
     481             : 
     482          40 :                         werror = dns_replace_records(dns, mem_ctx, dn,
     483             :                                                      needs_add, recs, rcount);
     484          40 :                         DBG_DEBUG("dns_replace_records(CNAME): %s\n", win_errstr(werror));
     485          40 :                         W_ERROR_NOT_OK_RETURN(werror);
     486             : 
     487          38 :                         return WERR_OK;
     488             :                 } else {
     489             :                         /*
     490             :                          * If there is a CNAME record for this name,
     491             :                          * ignore update
     492             :                          */
     493        4216 :                         for (i = first; i < rcount; i++) {
     494        3205 :                                 if (recs[i].wType == DNS_TYPE_CNAME) {
     495           0 :                                         DEBUG(5, ("Skipping update\n"));
     496           0 :                                         return WERR_OK;
     497             :                                 }
     498             :                         }
     499             :                 }
     500        1011 :                 if (update->rr_type == DNS_QTYPE_SOA) {
     501           0 :                         bool found = false;
     502             : 
     503             :                         /*
     504             :                          * If the zone has no SOA record?? or update's
     505             :                          * serial number is smaller than existing SOA's,
     506             :                          * ignore update
     507             :                          */
     508           0 :                         for (i = first; i < rcount; i++) {
     509           0 :                                 if (recs[i].wType == DNS_TYPE_SOA) {
     510           0 :                                         uint16_t n, o;
     511             : 
     512           0 :                                         n = update->rdata.soa_record.serial;
     513           0 :                                         o = recs[i].data.soa.serial;
     514             :                                         /*
     515             :                                          * TODO: Implement RFC 1982 comparison
     516             :                                          * logic for RFC2136
     517             :                                          */
     518           0 :                                         if (n <= o) {
     519           0 :                                                 DEBUG(5, ("Skipping update\n"));
     520           0 :                                                 return WERR_OK;
     521             :                                         }
     522           0 :                                         found = true;
     523           0 :                                         break;
     524             :                                 }
     525             :                         }
     526           0 :                         if (!found) {
     527           0 :                                 DEBUG(5, ("Skipping update\n"));
     528           0 :                                 return WERR_OK;
     529             :                         }
     530             : 
     531           0 :                         werror = dns_rr_to_dnsp(
     532           0 :                             mem_ctx, update, &recs[i], name_is_static);
     533           0 :                         DBG_DEBUG("dns_rr_to_dnsp(SOA): %s\n", win_errstr(werror));
     534           0 :                         W_ERROR_NOT_OK_RETURN(werror);
     535             : 
     536             :                         /*
     537             :                          * There should only be one SOA, which we have already
     538             :                          * found and replaced. We now check for and tombstone
     539             :                          * any others.
     540             :                          */
     541           0 :                         for (i++; i < rcount; i++) {
     542           0 :                                 if (recs[i].wType != DNS_TYPE_SOA) {
     543           0 :                                         continue;
     544             :                                 }
     545           0 :                                 DBG_ERR("Duplicate SOA records found.\n");
     546           0 :                                 if (DEBUGLVL(DBGLVL_ERR)) {
     547           0 :                                         NDR_PRINT_DEBUG(dns_res_rec,
     548             :                                                         discard_const(update));
     549             :                                 }
     550           0 :                                 recs[i] = (struct dnsp_DnssrvRpcRecord) {
     551             :                                         .wType = DNS_TYPE_TOMBSTONE,
     552             :                                 };
     553             :                         }
     554             : 
     555           0 :                         werror = dns_replace_records(dns, mem_ctx, dn,
     556             :                                                      needs_add, recs, rcount);
     557           0 :                         DBG_DEBUG("dns_replace_records(SOA): %s\n", win_errstr(werror));
     558           0 :                         W_ERROR_NOT_OK_RETURN(werror);
     559             : 
     560           0 :                         return WERR_OK;
     561             :                 }
     562             :                 /* All but CNAME, SOA */
     563        1011 :                 recs = talloc_realloc(mem_ctx, recs,
     564             :                                 struct dnsp_DnssrvRpcRecord, rcount+1);
     565        1011 :                 W_ERROR_HAVE_NO_MEMORY(recs);
     566             : 
     567           0 :                 werror =
     568        1011 :                     dns_rr_to_dnsp(recs, update, &recs[rcount], name_is_static);
     569        1011 :                 DBG_DEBUG("dns_rr_to_dnsp(GENERIC): %s\n", win_errstr(werror));
     570        1011 :                 W_ERROR_NOT_OK_RETURN(werror);
     571             : 
     572        3784 :                 for (i = first; i < rcount; i++) {
     573        3065 :                         if (!dns_record_match(&recs[i], &recs[rcount])) {
     574        2773 :                                 continue;
     575             :                         }
     576             : 
     577         292 :                         recs[i].data = recs[rcount].data;
     578         292 :                         recs[i].wType = recs[rcount].wType;
     579         292 :                         recs[i].dwTtlSeconds = recs[rcount].dwTtlSeconds;
     580         292 :                         recs[i].rank = recs[rcount].rank;
     581         292 :                         recs[i].dwReserved = 0;
     582         292 :                         recs[i].flags = 0;
     583         292 :                         werror = dns_replace_records(dns, mem_ctx, dn,
     584             :                                                      needs_add, recs, rcount);
     585         292 :                         DBG_DEBUG("dns_replace_records(REPLACE): %s\n", win_errstr(werror));
     586         584 :                         W_ERROR_NOT_OK_RETURN(werror);
     587             : 
     588         292 :                         return WERR_OK;
     589             :                 }
     590             :                 /* we did not find a matching record. This is new. */
     591         719 :                 werror = dns_replace_records(dns, mem_ctx, dn,
     592         719 :                                              needs_add, recs, rcount+1);
     593         719 :                 DBG_DEBUG("dns_replace_records(ADD): %s\n", win_errstr(werror));
     594         719 :                 W_ERROR_NOT_OK_RETURN(werror);
     595             : 
     596         719 :                 return WERR_OK;
     597         177 :         } else if (update->rr_class == DNS_QCLASS_ANY) {
     598             :                 /*
     599             :                  * Mass-deleting records by type, which we do by adding a
     600             :                  * tombstone with zero timestamp. dns_replace_records() will
     601             :                  * work out if the node as a whole needs tombstoning.
     602             :                  */
     603          48 :                 if (update->rr_type == DNS_QTYPE_ALL) {
     604          40 :                         if (samba_dns_name_equal(update->name, zone->name)) {
     605           0 :                                 for (i = first; i < rcount; i++) {
     606             : 
     607           0 :                                         if (recs[i].wType == DNS_TYPE_SOA) {
     608           0 :                                                 continue;
     609             :                                         }
     610             : 
     611           0 :                                         if (recs[i].wType == DNS_TYPE_NS) {
     612           0 :                                                 continue;
     613             :                                         }
     614             : 
     615           0 :                                         recs[i] = (struct dnsp_DnssrvRpcRecord) {
     616             :                                                 .wType = DNS_TYPE_TOMBSTONE,
     617             :                                         };
     618             :                                 }
     619             : 
     620             :                         } else {
     621          58 :                                 for (i = first; i < rcount; i++) {
     622          18 :                                         recs[i] = (struct dnsp_DnssrvRpcRecord) {
     623             :                                                 .wType = DNS_TYPE_TOMBSTONE,
     624             :                                         };
     625             :                                 }
     626             :                         }
     627             : 
     628           8 :                 } else if (samba_dns_name_equal(update->name, zone->name)) {
     629             : 
     630           0 :                         if (update->rr_type == DNS_QTYPE_SOA) {
     631           0 :                                 return WERR_OK;
     632             :                         }
     633             : 
     634           0 :                         if (update->rr_type == DNS_QTYPE_NS) {
     635           0 :                                 return WERR_OK;
     636             :                         }
     637             :                 }
     638         102 :                 for (i = first; i < rcount; i++) {
     639          54 :                         if (recs[i].wType == (enum dns_record_type) update->rr_type) {
     640          12 :                                 recs[i] = (struct dnsp_DnssrvRpcRecord) {
     641             :                                         .wType = DNS_TYPE_TOMBSTONE,
     642             :                                 };
     643             :                         }
     644             :                 }
     645             : 
     646          48 :                 werror = dns_replace_records(dns, mem_ctx, dn,
     647             :                                              needs_add, recs, rcount);
     648          48 :                 DBG_DEBUG("dns_replace_records(DELETE-ANY): %s\n", win_errstr(werror));
     649          48 :                 W_ERROR_NOT_OK_RETURN(werror);
     650             : 
     651          46 :                 return WERR_OK;
     652         129 :         } else if (update->rr_class == DNS_QCLASS_NONE) {
     653             :                 /* deleting individual records */
     654           0 :                 struct dnsp_DnssrvRpcRecord *del_rec;
     655             : 
     656         129 :                 if (update->rr_type == DNS_QTYPE_SOA) {
     657           0 :                         return WERR_OK;
     658             :                 }
     659         129 :                 if (update->rr_type == DNS_QTYPE_NS) {
     660           0 :                         bool found = false;
     661           0 :                         struct dnsp_DnssrvRpcRecord *ns_rec = talloc(mem_ctx,
     662             :                                                 struct dnsp_DnssrvRpcRecord);
     663           0 :                         W_ERROR_HAVE_NO_MEMORY(ns_rec);
     664             : 
     665           0 :                         werror = dns_rr_to_dnsp(
     666             :                             ns_rec, update, ns_rec, name_is_static);
     667           0 :                         DBG_DEBUG("dns_rr_to_dnsp(NS): %s\n", win_errstr(werror));
     668           0 :                         W_ERROR_NOT_OK_RETURN(werror);
     669             : 
     670           0 :                         for (i = first; i < rcount; i++) {
     671           0 :                                 if (dns_record_match(ns_rec, &recs[i])) {
     672           0 :                                         found = true;
     673           0 :                                         break;
     674             :                                 }
     675             :                         }
     676           0 :                         if (found) {
     677           0 :                                 return WERR_OK;
     678             :                         }
     679             :                 }
     680             : 
     681         129 :                 del_rec = talloc(mem_ctx, struct dnsp_DnssrvRpcRecord);
     682         129 :                 W_ERROR_HAVE_NO_MEMORY(del_rec);
     683             : 
     684           0 :                 werror =
     685         129 :                     dns_rr_to_dnsp(del_rec, update, del_rec, name_is_static);
     686         129 :                 DBG_DEBUG("dns_rr_to_dnsp(DELETE-NONE): %s\n", win_errstr(werror));
     687         129 :                 W_ERROR_NOT_OK_RETURN(werror);
     688             : 
     689         415 :                 for (i = first; i < rcount; i++) {
     690         286 :                         if (dns_record_match(del_rec, &recs[i])) {
     691         127 :                                 recs[i] = (struct dnsp_DnssrvRpcRecord) {
     692             :                                         .wType = DNS_TYPE_TOMBSTONE,
     693             :                                 };
     694             :                         }
     695             :                 }
     696             : 
     697         129 :                 werror = dns_replace_records(dns, mem_ctx, dn,
     698             :                                              needs_add, recs, rcount);
     699         129 :                 DBG_DEBUG("dns_replace_records(DELETE-NONE): %s\n", win_errstr(werror));
     700         129 :                 W_ERROR_NOT_OK_RETURN(werror);
     701             :         }
     702             : 
     703         129 :         return WERR_OK;
     704             : }
     705             : 
     706        1168 : static WERROR handle_updates(struct dns_server *dns,
     707             :                              TALLOC_CTX *mem_ctx,
     708             :                              const struct dns_name_question *zone,
     709             :                              const struct dns_res_rec *prereqs, uint16_t pcount,
     710             :                              struct dns_res_rec *updates, uint16_t upd_count,
     711             :                              struct dns_server_tkey *tkey)
     712             : {
     713        1168 :         struct ldb_dn *zone_dn = NULL;
     714        1168 :         WERROR werror = WERR_OK;
     715           0 :         int ret;
     716           0 :         uint16_t ri;
     717        1168 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     718             : 
     719        1168 :         if (tkey != NULL) {
     720          64 :                 ret = ldb_set_opaque(
     721             :                         dns->samdb,
     722             :                         DSDB_SESSION_INFO,
     723          64 :                         tkey->session_info);
     724          64 :                 if (ret != LDB_SUCCESS) {
     725           0 :                         DEBUG(1, ("unable to set session info\n"));
     726           0 :                         werror = DNS_ERR(SERVER_FAILURE);
     727           0 :                         goto failed;
     728             :                 }
     729             :         }
     730             : 
     731        1168 :         werror = dns_name2dn(dns, tmp_ctx, zone->name, &zone_dn);
     732        1168 :         DBG_DEBUG("dns_name2dn(): %s\n", win_errstr(werror));
     733        1168 :         W_ERROR_NOT_OK_GOTO(werror, failed);
     734             : 
     735        1168 :         ret = ldb_transaction_start(dns->samdb);
     736        1168 :         if (ret != LDB_SUCCESS) {
     737           0 :                 werror = DNS_ERR(SERVER_FAILURE);
     738           0 :                 goto failed;
     739             :         }
     740             : 
     741        1168 :         werror = check_prerequisites(dns, tmp_ctx, zone, prereqs, pcount);
     742        1168 :         W_ERROR_NOT_OK_GOTO(werror, failed);
     743             : 
     744        1168 :         DBG_DEBUG("dns update count is %u\n", upd_count);
     745             : 
     746        2392 :         for (ri = 0; ri < upd_count; ri++) {
     747        1228 :                 werror = handle_one_update(dns, tmp_ctx, zone,
     748        1228 :                                            &updates[ri], tkey);
     749        1228 :                 DBG_DEBUG("handle_one_update(%u): %s\n",
     750             :                           ri, win_errstr(werror));
     751        1228 :                 W_ERROR_NOT_OK_GOTO(werror, failed);
     752             :         }
     753             : 
     754        1164 : failed:
     755        1168 :         if (W_ERROR_IS_OK(werror)) {
     756        1164 :                 ret = ldb_transaction_commit(dns->samdb);
     757        1164 :                 if (ret != LDB_SUCCESS) {
     758           0 :                         werror = DNS_ERR(SERVER_FAILURE);
     759             :                 }
     760             :         } else {
     761           4 :                 ldb_transaction_cancel(dns->samdb);
     762             :         }
     763             : 
     764        1168 :         if (tkey != NULL) {
     765          64 :                 ldb_set_opaque(
     766             :                         dns->samdb,
     767             :                         DSDB_SESSION_INFO,
     768          64 :                         system_session(dns->task->lp_ctx));
     769             :         }
     770             : 
     771        1168 :         TALLOC_FREE(tmp_ctx);
     772        1168 :         return werror;
     773             : 
     774             : }
     775             : 
     776        1277 : static WERROR dns_update_allowed(struct dns_server *dns,
     777             :                                  const struct dns_request_state *state,
     778             :                                  struct dns_server_tkey **tkey)
     779             : {
     780        1277 :         if (lpcfg_allow_dns_updates(dns->task->lp_ctx) == DNS_UPDATE_ON) {
     781        1104 :                 DEBUG(2, ("All updates allowed.\n"));
     782        1104 :                 return WERR_OK;
     783             :         }
     784             : 
     785         173 :         if (lpcfg_allow_dns_updates(dns->task->lp_ctx) == DNS_UPDATE_OFF) {
     786           0 :                 DEBUG(2, ("Updates disabled.\n"));
     787           0 :                 return DNS_ERR(REFUSED);
     788             :         }
     789             : 
     790         173 :         if (state->authenticated == false ) {
     791         109 :                 DEBUG(2, ("Update not allowed for unsigned packet.\n"));
     792         109 :                 return DNS_ERR(REFUSED);
     793             :         }
     794             : 
     795          64 :         *tkey = dns_find_tkey(dns->tkeys, state->key_name);
     796          64 :         if (*tkey == NULL) {
     797           0 :                 DEBUG(0, ("Authenticated, but key not found. Something is wrong.\n"));
     798           0 :                 return DNS_ERR(REFUSED);
     799             :         }
     800             : 
     801          64 :         return WERR_OK;
     802             : }
     803             : 
     804             : 
     805        1331 : WERROR dns_server_process_update(struct dns_server *dns,
     806             :                                  const struct dns_request_state *state,
     807             :                                  TALLOC_CTX *mem_ctx,
     808             :                                  const struct dns_name_packet *in,
     809             :                                  struct dns_res_rec **prereqs,    uint16_t *prereq_count,
     810             :                                  struct dns_res_rec **updates,    uint16_t *update_count,
     811             :                                  struct dns_res_rec **additional, uint16_t *arcount)
     812             : {
     813           0 :         struct dns_name_question *zone;
     814           0 :         const struct dns_server_zone *z;
     815        1331 :         size_t host_part_len = 0;
     816        1331 :         WERROR werror = DNS_ERR(NOT_IMPLEMENTED);
     817        1331 :         struct dns_server_tkey *tkey = NULL;
     818             : 
     819        1331 :         if (in->qdcount != 1) {
     820           4 :                 return DNS_ERR(FORMAT_ERROR);
     821             :         }
     822             : 
     823        1327 :         zone = &in->questions[0];
     824             : 
     825        1327 :         if (zone->question_class != DNS_QCLASS_IN &&
     826           4 :             zone->question_class != DNS_QCLASS_ANY) {
     827           4 :                 return DNS_ERR(NOT_IMPLEMENTED);
     828             :         }
     829             : 
     830        1323 :         if (zone->question_type != DNS_QTYPE_SOA) {
     831           0 :                 return DNS_ERR(FORMAT_ERROR);
     832             :         }
     833             : 
     834        1323 :         DEBUG(2, ("Got a dns update request.\n"));
     835             : 
     836        2023 :         for (z = dns->zones; z != NULL; z = z->next) {
     837           0 :                 bool match;
     838             : 
     839        2023 :                 match = dns_name_match(z->name, zone->name, &host_part_len);
     840        2023 :                 if (match) {
     841        1323 :                         break;
     842             :                 }
     843             :         }
     844             : 
     845        1323 :         if (z == NULL) {
     846           0 :                 DEBUG(1, ("We're not authoritative for this zone\n"));
     847           0 :                 return DNS_ERR(NOTAUTH);
     848             :         }
     849             : 
     850        1323 :         if (host_part_len != 0) {
     851             :                 /* TODO: We need to delegate this one */
     852           0 :                 DEBUG(1, ("Would have to delegate zone '%s'.\n", zone->name));
     853           0 :                 return DNS_ERR(NOT_IMPLEMENTED);
     854             :         }
     855             : 
     856        1323 :         *prereq_count = in->ancount;
     857        1323 :         *prereqs = in->answers;
     858        1323 :         werror = check_prerequisites(dns, mem_ctx, in->questions, *prereqs,
     859        1323 :                                      *prereq_count);
     860        1323 :         W_ERROR_NOT_OK_RETURN(werror);
     861             : 
     862        1277 :         werror = dns_update_allowed(dns, state, &tkey);
     863        1277 :         if (!W_ERROR_IS_OK(werror)) {
     864         109 :                 return werror;
     865             :         }
     866             : 
     867        1168 :         *update_count = in->nscount;
     868        1168 :         *updates = in->nsrecs;
     869        1168 :         werror = update_prescan(in->questions, *updates, *update_count);
     870        1168 :         DBG_DEBUG("update_prescan(): %s\n", win_errstr(werror));
     871        1168 :         W_ERROR_NOT_OK_RETURN(werror);
     872             : 
     873        1168 :         werror = handle_updates(dns, mem_ctx, in->questions, *prereqs,
     874        1168 :                                 *prereq_count, *updates, *update_count, tkey);
     875        1168 :         DBG_DEBUG("handle_updates(): %s\n", win_errstr(werror));
     876        1168 :         W_ERROR_NOT_OK_RETURN(werror);
     877             : 
     878        1164 :         return werror;
     879             : }

Generated by: LCOV version 1.14