LCOV - code coverage report
Current view: top level - source4/dns_server - dns_update.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 300 420 71.4 %
Date: 2024-06-13 04:01:37 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         202 : 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             :         bool match;
      51             :         WERROR werror;
      52             :         struct ldb_dn *dn;
      53             :         uint16_t i;
      54         202 :         bool found = false;
      55         202 :         struct dnsp_DnssrvRpcRecord *rec = NULL;
      56             :         struct dnsp_DnssrvRpcRecord *ans;
      57             :         uint16_t acount;
      58             : 
      59         202 :         size_t host_part_len = 0;
      60             : 
      61         202 :         *final_result = true;
      62             : 
      63         202 :         if (pr->ttl != 0) {
      64           4 :                 return DNS_ERR(FORMAT_ERROR);
      65             :         }
      66             : 
      67         198 :         match = dns_name_match(zone->name, pr->name, &host_part_len);
      68         198 :         if (!match) {
      69           6 :                 return DNS_ERR(NOTZONE);
      70             :         }
      71             : 
      72         192 :         werror = dns_name2dn(dns, mem_ctx, pr->name, &dn);
      73         192 :         W_ERROR_NOT_OK_RETURN(werror);
      74             : 
      75         192 :         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, &acount);
      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 (acount == 0) {
      92           0 :                                 return DNS_ERR(NAME_ERROR);
      93             :                         }
      94             :                 } else {
      95             :                         /*
      96             :                          */
      97           8 :                         werror = dns_lookup_records(dns, mem_ctx, dn, &ans, &acount);
      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 < acount; 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         184 :         if (pr->rr_class == DNS_QCLASS_NONE) {
     126         134 :                 if (pr->length != 0) {
     127           0 :                         return DNS_ERR(FORMAT_ERROR);
     128             :                 }
     129             : 
     130         134 :                 if (pr->rr_type == DNS_QTYPE_ALL) {
     131             :                         /*
     132             :                          */
     133           0 :                         werror = dns_lookup_records(dns, mem_ctx, dn, &ans, &acount);
     134           0 :                         if (W_ERROR_EQUAL(werror, WERR_OK)) {
     135           0 :                                 return DNS_ERR(YXDOMAIN);
     136             :                         }
     137             :                 } else {
     138             :                         /*
     139             :                          */
     140         134 :                         werror = dns_lookup_records(dns, mem_ctx, dn, &ans, &acount);
     141         134 :                         if (W_ERROR_EQUAL(werror, WERR_DNS_ERROR_NAME_DOES_NOT_EXIST)) {
     142         110 :                                 werror = WERR_OK;
     143             :                         }
     144         134 :                         if (W_ERROR_EQUAL(werror, DNS_ERR(NAME_ERROR))) {
     145           0 :                                 werror = WERR_OK;
     146             :                         }
     147             : 
     148         166 :                         for (i = 0; i < acount; i++) {
     149          32 :                                 if (ans[i].wType == (enum dns_record_type) pr->rr_type) {
     150           0 :                                         found = true;
     151           0 :                                         break;
     152             :                                 }
     153             :                         }
     154         134 :                         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         134 :                 return WERR_OK;
     165             :         }
     166             : 
     167          50 :         if (pr->rr_class != zone->question_class) {
     168           0 :                 return DNS_ERR(FORMAT_ERROR);
     169             :         }
     170             : 
     171          50 :         *final_result = false;
     172             : 
     173          50 :         werror = dns_lookup_records(dns, mem_ctx, dn, &ans, &acount);
     174          50 :         if (W_ERROR_EQUAL(werror, WERR_DNS_ERROR_NAME_DOES_NOT_EXIST)) {
     175          44 :                 return DNS_ERR(NXRRSET);
     176             :         }
     177           6 :         if (W_ERROR_EQUAL(werror, DNS_ERR(NAME_ERROR))) {
     178           0 :                 return DNS_ERR(NXRRSET);
     179             :         }
     180           6 :         W_ERROR_NOT_OK_RETURN(werror);
     181             : 
     182           6 :         rec = talloc_zero(mem_ctx, struct dnsp_DnssrvRpcRecord);
     183           6 :         W_ERROR_HAVE_NO_MEMORY(rec);
     184             : 
     185           6 :         werror = dns_rr_to_dnsp(rec, pr, rec, dns_name_is_static(ans, acount));
     186           6 :         W_ERROR_NOT_OK_RETURN(werror);
     187             : 
     188          10 :         for (i = 0; i < acount; i++) {
     189           6 :                 if (dns_record_match(rec, &ans[i])) {
     190           2 :                         found = true;
     191           2 :                         break;
     192             :                 }
     193             :         }
     194             : 
     195           6 :         if (!found) {
     196           4 :                 return DNS_ERR(NXRRSET);
     197             :         }
     198             : 
     199           2 :         return WERR_OK;
     200             : }
     201             : 
     202        2729 : 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             :         uint16_t i;
     208        2729 :         WERROR final_error = WERR_OK;
     209             : 
     210        2913 :         for (i = 0; i < count; i++) {
     211             :                 bool final;
     212             :                 WERROR werror;
     213             : 
     214         202 :                 werror = check_one_prerequisite(dns, mem_ctx, zone,
     215         202 :                                                 &prereqs[i], &final);
     216         202 :                 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        2711 :         if (!W_ERROR_IS_OK(final_error)) {
     227          28 :                 return final_error;
     228             :         }
     229             : 
     230        2683 :         return WERR_OK;
     231             : }
     232             : 
     233        1295 : static WERROR update_prescan(const struct dns_name_question *zone,
     234             :                              const struct dns_res_rec *updates, uint16_t count)
     235             : {
     236             :         const struct dns_res_rec *r;
     237             :         uint16_t i;
     238             :         size_t host_part_len;
     239             :         bool match;
     240             : 
     241        2648 :         for (i = 0; i < count; i++) {
     242        1353 :                 r = &updates[i];
     243        1353 :                 match = dns_name_match(zone->name, r->name, &host_part_len);
     244        1353 :                 if (!match) {
     245           0 :                         return DNS_ERR(NOTZONE);
     246             :                 }
     247        1353 :                 if (zone->question_class == r->rr_class) {
     248        1184 :                         if (r->rr_type == DNS_QTYPE_ALL) {
     249           0 :                                 return DNS_ERR(FORMAT_ERROR);
     250             :                         }
     251        1184 :                         if (r->rr_type == DNS_QTYPE_AXFR) {
     252           0 :                                 return DNS_ERR(FORMAT_ERROR);
     253             :                         }
     254        1184 :                         if (r->rr_type == DNS_QTYPE_MAILB) {
     255           0 :                                 return DNS_ERR(FORMAT_ERROR);
     256             :                         }
     257        1184 :                         if (r->rr_type == DNS_QTYPE_MAILA) {
     258           0 :                                 return DNS_ERR(FORMAT_ERROR);
     259             :                         }
     260         169 :                 } else if (r->rr_class == DNS_QCLASS_ANY) {
     261          40 :                         if (r->ttl != 0) {
     262           0 :                                 return DNS_ERR(FORMAT_ERROR);
     263             :                         }
     264          40 :                         if (r->length != 0) {
     265           0 :                                 return DNS_ERR(FORMAT_ERROR);
     266             :                         }
     267          40 :                         if (r->rr_type == DNS_QTYPE_AXFR) {
     268           0 :                                 return DNS_ERR(FORMAT_ERROR);
     269             :                         }
     270          40 :                         if (r->rr_type == DNS_QTYPE_MAILB) {
     271           0 :                                 return DNS_ERR(FORMAT_ERROR);
     272             :                         }
     273          40 :                         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        1295 :         return WERR_OK;
     297             : }
     298             : 
     299        1317 : 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             :         enum ndr_err_code ndr_err;
     305             : 
     306        1317 :         if (rrec->rr_type == DNS_QTYPE_ALL) {
     307           0 :                 return DNS_ERR(FORMAT_ERROR);
     308             :         }
     309             : 
     310        1317 :         ZERO_STRUCTP(r);
     311             : 
     312        1317 :         r->wType = (enum dns_record_type) rrec->rr_type;
     313        1317 :         r->dwTtlSeconds = rrec->ttl;
     314        1317 :         r->rank = DNS_RANK_ZONE;
     315        1317 :         if (name_is_static) {
     316         247 :                 r->dwTimeStamp = 0;
     317             :         } else {
     318        1070 :                 r->dwTimeStamp = unix_to_dns_timestamp(time(NULL));
     319             :         }
     320             : 
     321             :         /* If we get QCLASS_ANY, we're done here */
     322        1317 :         if (rrec->rr_class == DNS_QCLASS_ANY) {
     323           0 :                 goto done;
     324             :         }
     325             : 
     326        1317 :         switch(rrec->rr_type) {
     327         232 :         case DNS_QTYPE_A:
     328         232 :                 r->data.ipv4 = talloc_strdup(mem_ctx, rrec->rdata.ipv4_record);
     329         232 :                 W_ERROR_HAVE_NO_MEMORY(r->data.ipv4);
     330         711 :                 break;
     331         128 :         case DNS_QTYPE_AAAA:
     332         128 :                 r->data.ipv6 = talloc_strdup(mem_ctx, rrec->rdata.ipv6_record);
     333         128 :                 W_ERROR_HAVE_NO_MEMORY(r->data.ipv6);
     334         128 :                 break;
     335           6 :         case DNS_QTYPE_NS:
     336           6 :                 r->data.ns = talloc_strdup(mem_ctx, rrec->rdata.ns_record);
     337           6 :                 W_ERROR_HAVE_NO_MEMORY(r->data.ns);
     338           6 :                 break;
     339          45 :         case DNS_QTYPE_CNAME:
     340          45 :                 r->data.cname = talloc_strdup(mem_ctx, rrec->rdata.cname_record);
     341          45 :                 W_ERROR_HAVE_NO_MEMORY(r->data.cname);
     342          45 :                 break;
     343         146 :         case DNS_QTYPE_SRV:
     344         146 :                 r->data.srv.wPriority = rrec->rdata.srv_record.priority;
     345         146 :                 r->data.srv.wWeight = rrec->rdata.srv_record.weight;
     346         146 :                 r->data.srv.wPort = rrec->rdata.srv_record.port;
     347         171 :                 r->data.srv.nameTarget = talloc_strdup(mem_ctx,
     348          25 :                                 rrec->rdata.srv_record.target);
     349         146 :                 W_ERROR_HAVE_NO_MEMORY(r->data.srv.nameTarget);
     350         146 :                 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           3 :                 r->data.mx.nameTarget = talloc_strdup(mem_ctx,
     358           1 :                                 rrec->rdata.mx_record.exchange);
     359           2 :                 W_ERROR_HAVE_NO_MEMORY(r->data.mx.nameTarget);
     360           2 :                 break;
     361         758 :         case DNS_QTYPE_TXT:
     362         758 :                 ndr_err = ndr_dnsp_string_list_copy(mem_ctx,
     363             :                                                     &rrec->rdata.txt_record.txt,
     364             :                                                     &r->data.txt);
     365         758 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     366           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     367             :                 }
     368             : 
     369         758 :                 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        1317 : done:
     376             : 
     377        1317 :         return WERR_OK;
     378             : }
     379             : 
     380             : 
     381        1351 : 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        1351 :         struct dnsp_DnssrvRpcRecord *recs = NULL;
     388        1351 :         uint16_t rcount = 0;
     389             :         struct ldb_dn *dn;
     390             :         uint16_t i;
     391        1351 :         uint16_t first = 0;
     392             :         WERROR werror;
     393        1351 :         bool tombstoned = false;
     394        1351 :         bool needs_add = false;
     395             :         bool name_is_static;
     396             : 
     397        1351 :         DEBUG(2, ("Looking at record: \n"));
     398        1351 :         if (DEBUGLVL(2)) {
     399           0 :                 NDR_PRINT_DEBUG(dns_res_rec, discard_const(update));
     400             :         }
     401             : 
     402        1351 :         switch (update->rr_type) {
     403        1351 :         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        1351 :                 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        1351 :         werror = dns_name2dn(dns, mem_ctx, update->name, &dn);
     421        1351 :         W_ERROR_NOT_OK_RETURN(werror);
     422             : 
     423        1351 :         werror = dns_common_lookup(dns->samdb, mem_ctx, dn,
     424             :                                    &recs, &rcount, &tombstoned);
     425        1351 :         if (W_ERROR_EQUAL(werror, WERR_DNS_ERROR_NAME_DOES_NOT_EXIST)) {
     426         340 :                 needs_add = true;
     427         340 :                 werror = WERR_OK;
     428             :         }
     429        1351 :         W_ERROR_NOT_OK_RETURN(werror);
     430             : 
     431        1351 :         if (tombstoned) {
     432             :                 /*
     433             :                  * we need to keep the existing tombstone record
     434             :                  * and ignore it.
     435             :                  *
     436             :                  * There *should* only be a single record of type TOMBSTONE,
     437             :                  * but we don't insist.
     438             :                  */
     439          18 :                 if (rcount != 1) {
     440           0 :                         DBG_WARNING("Tombstoned dnsNode has %u records, "
     441             :                                     "expected 1\n", rcount);
     442           0 :                         if (DEBUGLVL(1)) {
     443           0 :                                 NDR_PRINT_DEBUG(dns_res_rec, discard_const(update));
     444             :                         }
     445             :                 }
     446          18 :                 first = rcount;
     447             :         }
     448             : 
     449        1351 :         name_is_static = dns_name_is_static(recs, rcount);
     450             : 
     451        1351 :         if (update->rr_class == zone->question_class) {
     452        1182 :                 if (update->rr_type == DNS_QTYPE_CNAME) {
     453             :                         /*
     454             :                          * If there is a record in the directory
     455             :                          * that's not a CNAME, ignore update
     456             :                          */
     457          66 :                         for (i = first; i < rcount; i++) {
     458          10 :                                 if (recs[i].wType != DNS_TYPE_CNAME) {
     459           0 :                                         DEBUG(5, ("Skipping update\n"));
     460           0 :                                         return WERR_OK;
     461             :                                 }
     462          10 :                                 break;
     463             :                         }
     464             : 
     465             :                         /*
     466             :                          * There should be no entries besides one CNAME record
     467             :                          * per name, so replace everything with the new CNAME
     468             :                          */
     469             : 
     470          43 :                         rcount = first;
     471          43 :                         recs = talloc_realloc(mem_ctx, recs,
     472             :                                         struct dnsp_DnssrvRpcRecord, rcount + 1);
     473          43 :                         W_ERROR_HAVE_NO_MEMORY(recs);
     474             : 
     475          66 :                         werror = dns_rr_to_dnsp(
     476          43 :                             recs, update, &recs[rcount], name_is_static);
     477          43 :                         W_ERROR_NOT_OK_RETURN(werror);
     478          43 :                         rcount += 1;
     479             : 
     480          43 :                         werror = dns_replace_records(dns, mem_ctx, dn,
     481             :                                                      needs_add, recs, rcount);
     482          43 :                         W_ERROR_NOT_OK_RETURN(werror);
     483             : 
     484          41 :                         return WERR_OK;
     485             :                 } else {
     486             :                         /*
     487             :                          * If there is a CNAME record for this name,
     488             :                          * ignore update
     489             :                          */
     490        4537 :                         for (i = first; i < rcount; i++) {
     491        3398 :                                 if (recs[i].wType == DNS_TYPE_CNAME) {
     492           0 :                                         DEBUG(5, ("Skipping update\n"));
     493           0 :                                         return WERR_OK;
     494             :                                 }
     495             :                         }
     496             :                 }
     497        1139 :                 if (update->rr_type == DNS_QTYPE_SOA) {
     498           0 :                         bool found = false;
     499             : 
     500             :                         /*
     501             :                          * If the zone has no SOA record?? or update's
     502             :                          * serial number is smaller than existing SOA's,
     503             :                          * ignore update
     504             :                          */
     505           0 :                         for (i = first; i < rcount; i++) {
     506           0 :                                 if (recs[i].wType == DNS_TYPE_SOA) {
     507             :                                         uint16_t n, o;
     508             : 
     509           0 :                                         n = update->rdata.soa_record.serial;
     510           0 :                                         o = recs[i].data.soa.serial;
     511             :                                         /*
     512             :                                          * TODO: Implement RFC 1982 comparison
     513             :                                          * logic for RFC2136
     514             :                                          */
     515           0 :                                         if (n <= o) {
     516           0 :                                                 DEBUG(5, ("Skipping update\n"));
     517           0 :                                                 return WERR_OK;
     518             :                                         }
     519           0 :                                         found = true;
     520           0 :                                         break;
     521             :                                 }
     522             :                         }
     523           0 :                         if (!found) {
     524           0 :                                 DEBUG(5, ("Skipping update\n"));
     525           0 :                                 return WERR_OK;
     526             :                         }
     527             : 
     528           0 :                         werror = dns_rr_to_dnsp(
     529           0 :                             mem_ctx, update, &recs[i], name_is_static);
     530           0 :                         W_ERROR_NOT_OK_RETURN(werror);
     531             : 
     532             :                         /*
     533             :                          * There should only be one SOA, which we have already
     534             :                          * found and replaced. We now check for and tombstone
     535             :                          * any others.
     536             :                          */
     537           0 :                         for (i++; i < rcount; i++) {
     538           0 :                                 if (recs[i].wType != DNS_TYPE_SOA) {
     539           0 :                                         continue;
     540             :                                 }
     541           0 :                                 DBG_ERR("Duplicate SOA records found.\n");
     542           0 :                                 if (DEBUGLVL(0)) {
     543           0 :                                         NDR_PRINT_DEBUG(dns_res_rec,
     544             :                                                         discard_const(update));
     545             :                                 }
     546           0 :                                 recs[i] = (struct dnsp_DnssrvRpcRecord) {
     547             :                                         .wType = DNS_TYPE_TOMBSTONE,
     548             :                                 };
     549             :                         }
     550             : 
     551           0 :                         werror = dns_replace_records(dns, mem_ctx, dn,
     552             :                                                      needs_add, recs, rcount);
     553           0 :                         W_ERROR_NOT_OK_RETURN(werror);
     554             : 
     555           0 :                         return WERR_OK;
     556             :                 }
     557             :                 /* All but CNAME, SOA */
     558        1139 :                 recs = talloc_realloc(mem_ctx, recs,
     559             :                                 struct dnsp_DnssrvRpcRecord, rcount+1);
     560        1139 :                 W_ERROR_HAVE_NO_MEMORY(recs);
     561             : 
     562         640 :                 werror =
     563        1139 :                     dns_rr_to_dnsp(recs, update, &recs[rcount], name_is_static);
     564        1139 :                 W_ERROR_NOT_OK_RETURN(werror);
     565             : 
     566        6336 :                 for (i = first; i < rcount; i++) {
     567        3258 :                         if (!dns_record_match(&recs[i], &recs[rcount])) {
     568        2970 :                                 continue;
     569             :                         }
     570             : 
     571         288 :                         recs[i].data = recs[rcount].data;
     572         288 :                         recs[i].wType = recs[rcount].wType;
     573         288 :                         recs[i].dwTtlSeconds = recs[rcount].dwTtlSeconds;
     574         288 :                         recs[i].rank = recs[rcount].rank;
     575         288 :                         recs[i].dwReserved = 0;
     576         288 :                         recs[i].flags = 0;
     577         288 :                         werror = dns_replace_records(dns, mem_ctx, dn,
     578             :                                                      needs_add, recs, rcount);
     579         432 :                         W_ERROR_NOT_OK_RETURN(werror);
     580             : 
     581         288 :                         return WERR_OK;
     582             :                 }
     583             :                 /* we did not find a matching record. This is new. */
     584         851 :                 werror = dns_replace_records(dns, mem_ctx, dn,
     585         851 :                                              needs_add, recs, rcount+1);
     586         851 :                 W_ERROR_NOT_OK_RETURN(werror);
     587             : 
     588         851 :                 return WERR_OK;
     589         169 :         } else if (update->rr_class == DNS_QCLASS_ANY) {
     590             :                 /*
     591             :                  * Mass-deleting records by type, which we do by adding a
     592             :                  * tombstone with zero timestamp. dns_replace_records() will
     593             :                  * work out if the node as a whole needs tombstoning.
     594             :                  */
     595          40 :                 if (update->rr_type == DNS_QTYPE_ALL) {
     596          32 :                         if (samba_dns_name_equal(update->name, zone->name)) {
     597           0 :                                 for (i = first; i < rcount; i++) {
     598             : 
     599           0 :                                         if (recs[i].wType == DNS_TYPE_SOA) {
     600           0 :                                                 continue;
     601             :                                         }
     602             : 
     603           0 :                                         if (recs[i].wType == DNS_TYPE_NS) {
     604           0 :                                                 continue;
     605             :                                         }
     606             : 
     607           0 :                                         recs[i] = (struct dnsp_DnssrvRpcRecord) {
     608             :                                                 .wType = DNS_TYPE_TOMBSTONE,
     609             :                                         };
     610             :                                 }
     611             : 
     612             :                         } else {
     613          40 :                                 for (i = first; i < rcount; i++) {
     614           8 :                                         recs[i] = (struct dnsp_DnssrvRpcRecord) {
     615             :                                                 .wType = DNS_TYPE_TOMBSTONE,
     616             :                                         };
     617             :                                 }
     618             :                         }
     619             : 
     620           8 :                 } else if (samba_dns_name_equal(update->name, zone->name)) {
     621             : 
     622           0 :                         if (update->rr_type == DNS_QTYPE_SOA) {
     623           0 :                                 return WERR_OK;
     624             :                         }
     625             : 
     626           0 :                         if (update->rr_type == DNS_QTYPE_NS) {
     627           0 :                                 return WERR_OK;
     628             :                         }
     629             :                 }
     630          84 :                 for (i = first; i < rcount; i++) {
     631          44 :                         if (recs[i].wType == (enum dns_record_type) update->rr_type) {
     632          12 :                                 recs[i] = (struct dnsp_DnssrvRpcRecord) {
     633             :                                         .wType = DNS_TYPE_TOMBSTONE,
     634             :                                 };
     635             :                         }
     636             :                 }
     637             : 
     638          40 :                 werror = dns_replace_records(dns, mem_ctx, dn,
     639             :                                              needs_add, recs, rcount);
     640          40 :                 W_ERROR_NOT_OK_RETURN(werror);
     641             : 
     642          38 :                 return WERR_OK;
     643         129 :         } else if (update->rr_class == DNS_QCLASS_NONE) {
     644             :                 /* deleting individual records */
     645             :                 struct dnsp_DnssrvRpcRecord *del_rec;
     646             : 
     647         129 :                 if (update->rr_type == DNS_QTYPE_SOA) {
     648           0 :                         return WERR_OK;
     649             :                 }
     650         129 :                 if (update->rr_type == DNS_QTYPE_NS) {
     651           0 :                         bool found = false;
     652           0 :                         struct dnsp_DnssrvRpcRecord *ns_rec = talloc(mem_ctx,
     653             :                                                 struct dnsp_DnssrvRpcRecord);
     654           0 :                         W_ERROR_HAVE_NO_MEMORY(ns_rec);
     655             : 
     656           0 :                         werror = dns_rr_to_dnsp(
     657             :                             ns_rec, update, ns_rec, name_is_static);
     658           0 :                         W_ERROR_NOT_OK_RETURN(werror);
     659             : 
     660           0 :                         for (i = first; i < rcount; i++) {
     661           0 :                                 if (dns_record_match(ns_rec, &recs[i])) {
     662           0 :                                         found = true;
     663           0 :                                         break;
     664             :                                 }
     665             :                         }
     666           0 :                         if (found) {
     667           0 :                                 return WERR_OK;
     668             :                         }
     669             :                 }
     670             : 
     671         129 :                 del_rec = talloc(mem_ctx, struct dnsp_DnssrvRpcRecord);
     672         129 :                 W_ERROR_HAVE_NO_MEMORY(del_rec);
     673             : 
     674          72 :                 werror =
     675         129 :                     dns_rr_to_dnsp(del_rec, update, del_rec, name_is_static);
     676         129 :                 W_ERROR_NOT_OK_RETURN(werror);
     677             : 
     678         415 :                 for (i = first; i < rcount; i++) {
     679         286 :                         if (dns_record_match(del_rec, &recs[i])) {
     680         127 :                                 recs[i] = (struct dnsp_DnssrvRpcRecord) {
     681             :                                         .wType = DNS_TYPE_TOMBSTONE,
     682             :                                 };
     683             :                         }
     684             :                 }
     685             : 
     686         129 :                 werror = dns_replace_records(dns, mem_ctx, dn,
     687             :                                              needs_add, recs, rcount);
     688         129 :                 W_ERROR_NOT_OK_RETURN(werror);
     689             :         }
     690             : 
     691         129 :         return WERR_OK;
     692             : }
     693             : 
     694        1295 : static WERROR handle_updates(struct dns_server *dns,
     695             :                              TALLOC_CTX *mem_ctx,
     696             :                              const struct dns_name_question *zone,
     697             :                              const struct dns_res_rec *prereqs, uint16_t pcount,
     698             :                              struct dns_res_rec *updates, uint16_t upd_count,
     699             :                              struct dns_server_tkey *tkey)
     700             : {
     701        1295 :         struct ldb_dn *zone_dn = NULL;
     702        1295 :         WERROR werror = WERR_OK;
     703             :         int ret;
     704             :         uint16_t ri;
     705        1295 :         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
     706             : 
     707        1295 :         if (tkey != NULL) {
     708         195 :                 ret = ldb_set_opaque(
     709             :                         dns->samdb,
     710             :                         DSDB_SESSION_INFO,
     711         195 :                         tkey->session_info);
     712         195 :                 if (ret != LDB_SUCCESS) {
     713           0 :                         DEBUG(1, ("unable to set session info\n"));
     714           0 :                         werror = DNS_ERR(SERVER_FAILURE);
     715           0 :                         goto failed;
     716             :                 }
     717             :         }
     718             : 
     719        1295 :         werror = dns_name2dn(dns, tmp_ctx, zone->name, &zone_dn);
     720        1295 :         W_ERROR_NOT_OK_GOTO(werror, failed);
     721             : 
     722        1295 :         ret = ldb_transaction_start(dns->samdb);
     723        1295 :         if (ret != LDB_SUCCESS) {
     724           0 :                 werror = DNS_ERR(SERVER_FAILURE);
     725           0 :                 goto failed;
     726             :         }
     727             : 
     728        1295 :         werror = check_prerequisites(dns, tmp_ctx, zone, prereqs, pcount);
     729        1295 :         W_ERROR_NOT_OK_GOTO(werror, failed);
     730             : 
     731        1295 :         DBG_DEBUG("dns update count is %u\n", upd_count);
     732             : 
     733        2642 :         for (ri = 0; ri < upd_count; ri++) {
     734        1351 :                 werror = handle_one_update(dns, tmp_ctx, zone,
     735        1351 :                                            &updates[ri], tkey);
     736        1351 :                 W_ERROR_NOT_OK_GOTO(werror, failed);
     737             :         }
     738             : 
     739        1291 :         ldb_transaction_commit(dns->samdb);
     740        1291 :         TALLOC_FREE(tmp_ctx);
     741             : 
     742        1291 :         if (tkey != NULL) {
     743         193 :                 ldb_set_opaque(
     744             :                         dns->samdb,
     745             :                         DSDB_SESSION_INFO,
     746         193 :                         system_session(dns->task->lp_ctx));
     747             :         }
     748             : 
     749        1291 :         return WERR_OK;
     750             : 
     751           4 : failed:
     752           4 :         ldb_transaction_cancel(dns->samdb);
     753             : 
     754           4 :         if (tkey != NULL) {
     755           2 :                 ldb_set_opaque(
     756             :                         dns->samdb,
     757             :                         DSDB_SESSION_INFO,
     758           2 :                         system_session(dns->task->lp_ctx));
     759             :         }
     760             : 
     761           4 :         TALLOC_FREE(tmp_ctx);
     762           4 :         return werror;
     763             : 
     764             : }
     765             : 
     766        1388 : static WERROR dns_update_allowed(struct dns_server *dns,
     767             :                                  const struct dns_request_state *state,
     768             :                                  struct dns_server_tkey **tkey)
     769             : {
     770        1388 :         if (lpcfg_allow_dns_updates(dns->task->lp_ctx) == DNS_UPDATE_ON) {
     771        1100 :                 DEBUG(2, ("All updates allowed.\n"));
     772        1100 :                 return WERR_OK;
     773             :         }
     774             : 
     775         288 :         if (lpcfg_allow_dns_updates(dns->task->lp_ctx) == DNS_UPDATE_OFF) {
     776           0 :                 DEBUG(2, ("Updates disabled.\n"));
     777           0 :                 return DNS_ERR(REFUSED);
     778             :         }
     779             : 
     780         288 :         if (state->authenticated == false ) {
     781          93 :                 DEBUG(2, ("Update not allowed for unsigned packet.\n"));
     782          93 :                 return DNS_ERR(REFUSED);
     783             :         }
     784             : 
     785         195 :         *tkey = dns_find_tkey(dns->tkeys, state->key_name);
     786         195 :         if (*tkey == NULL) {
     787           0 :                 DEBUG(0, ("Authenticated, but key not found. Something is wrong.\n"));
     788           0 :                 return DNS_ERR(REFUSED);
     789             :         }
     790             : 
     791         195 :         return WERR_OK;
     792             : }
     793             : 
     794             : 
     795        1442 : WERROR dns_server_process_update(struct dns_server *dns,
     796             :                                  const struct dns_request_state *state,
     797             :                                  TALLOC_CTX *mem_ctx,
     798             :                                  const struct dns_name_packet *in,
     799             :                                  struct dns_res_rec **prereqs,    uint16_t *prereq_count,
     800             :                                  struct dns_res_rec **updates,    uint16_t *update_count,
     801             :                                  struct dns_res_rec **additional, uint16_t *arcount)
     802             : {
     803             :         struct dns_name_question *zone;
     804             :         const struct dns_server_zone *z;
     805        1442 :         size_t host_part_len = 0;
     806        1442 :         WERROR werror = DNS_ERR(NOT_IMPLEMENTED);
     807        1442 :         struct dns_server_tkey *tkey = NULL;
     808             : 
     809        1442 :         if (in->qdcount != 1) {
     810           4 :                 return DNS_ERR(FORMAT_ERROR);
     811             :         }
     812             : 
     813        1438 :         zone = &in->questions[0];
     814             : 
     815        1441 :         if (zone->question_class != DNS_QCLASS_IN &&
     816           4 :             zone->question_class != DNS_QCLASS_ANY) {
     817           4 :                 return DNS_ERR(NOT_IMPLEMENTED);
     818             :         }
     819             : 
     820        1434 :         if (zone->question_type != DNS_QTYPE_SOA) {
     821           0 :                 return DNS_ERR(FORMAT_ERROR);
     822             :         }
     823             : 
     824        1434 :         DEBUG(2, ("Got a dns update request.\n"));
     825             : 
     826        2166 :         for (z = dns->zones; z != NULL; z = z->next) {
     827             :                 bool match;
     828             : 
     829        2166 :                 match = dns_name_match(z->name, zone->name, &host_part_len);
     830        2166 :                 if (match) {
     831        1434 :                         break;
     832             :                 }
     833             :         }
     834             : 
     835        1434 :         if (z == NULL) {
     836           0 :                 DEBUG(1, ("We're not authoritative for this zone\n"));
     837           0 :                 return DNS_ERR(NOTAUTH);
     838             :         }
     839             : 
     840        1434 :         if (host_part_len != 0) {
     841             :                 /* TODO: We need to delegate this one */
     842           0 :                 DEBUG(1, ("Would have to delegate zone '%s'.\n", zone->name));
     843           0 :                 return DNS_ERR(NOT_IMPLEMENTED);
     844             :         }
     845             : 
     846        1434 :         *prereq_count = in->ancount;
     847        1434 :         *prereqs = in->answers;
     848        1434 :         werror = check_prerequisites(dns, mem_ctx, in->questions, *prereqs,
     849        1434 :                                      *prereq_count);
     850        1434 :         W_ERROR_NOT_OK_RETURN(werror);
     851             : 
     852        1388 :         werror = dns_update_allowed(dns, state, &tkey);
     853        1388 :         if (!W_ERROR_IS_OK(werror)) {
     854          93 :                 return werror;
     855             :         }
     856             : 
     857        1295 :         *update_count = in->nscount;
     858        1295 :         *updates = in->nsrecs;
     859        1295 :         werror = update_prescan(in->questions, *updates, *update_count);
     860        1295 :         W_ERROR_NOT_OK_RETURN(werror);
     861             : 
     862        2745 :         werror = handle_updates(dns, mem_ctx, in->questions, *prereqs,
     863        2020 :                                 *prereq_count, *updates, *update_count, tkey);
     864        1295 :         W_ERROR_NOT_OK_RETURN(werror);
     865             : 
     866        1291 :         return werror;
     867             : }

Generated by: LCOV version 1.13