LCOV - code coverage report
Current view: top level - source4/dns_server - dns_query.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 425 620 68.5 %
Date: 2024-04-21 15:09:00 Functions: 20 20 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    DNS server handler for queries
       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 "samba/service_task.h"
      24             : #include "libcli/util/werror.h"
      25             : #include "librpc/ndr/libndr.h"
      26             : #include "librpc/gen_ndr/ndr_dns.h"
      27             : #include "librpc/gen_ndr/ndr_dnsp.h"
      28             : #include <ldb.h>
      29             : #include "param/param.h"
      30             : #include "dsdb/samdb/samdb.h"
      31             : #include "dsdb/common/util.h"
      32             : #include "dns_server/dns_server.h"
      33             : #include "libcli/dns/libdns.h"
      34             : #include "lib/util/dlinklist.h"
      35             : #include "lib/util/util_net.h"
      36             : #include "lib/util/tevent_werror.h"
      37             : #include "auth/auth.h"
      38             : #include "auth/credentials/credentials.h"
      39             : #include "auth/gensec/gensec.h"
      40             : 
      41             : #undef DBGC_CLASS
      42             : #define DBGC_CLASS DBGC_DNS
      43             : #define MAX_Q_RECURSION_DEPTH 20
      44             : 
      45             : struct forwarder_string {
      46             :         const char *forwarder;
      47             :         struct forwarder_string *prev, *next;
      48             : };
      49             : 
      50        5469 : static WERROR add_response_rr(const char *name,
      51             :                               const struct dnsp_DnssrvRpcRecord *rec,
      52             :                               struct dns_res_rec **answers)
      53             : {
      54        5469 :         struct dns_res_rec *ans = *answers;
      55        5469 :         uint16_t ai = talloc_array_length(ans);
      56           0 :         enum ndr_err_code ndr_err;
      57             : 
      58        5469 :         if (ai == UINT16_MAX) {
      59           0 :                 return WERR_BUFFER_OVERFLOW;
      60             :         }
      61             : 
      62             :         /*
      63             :          * "ans" is always non-NULL and thus its own talloc context
      64             :          */
      65        5469 :         ans = talloc_realloc(ans, ans, struct dns_res_rec, ai+1);
      66        5469 :         if (ans == NULL) {
      67           0 :                 return WERR_NOT_ENOUGH_MEMORY;
      68             :         }
      69             : 
      70        5469 :         ZERO_STRUCT(ans[ai]);
      71             : 
      72        5469 :         switch (rec->wType) {
      73          79 :         case DNS_QTYPE_CNAME:
      74          79 :                 ans[ai].rdata.cname_record = talloc_strdup(ans, rec->data.cname);
      75          79 :                 W_ERROR_HAVE_NO_MEMORY(ans[ai].rdata.cname_record);
      76          79 :                 break;
      77         765 :         case DNS_QTYPE_A:
      78         765 :                 ans[ai].rdata.ipv4_record = talloc_strdup(ans, rec->data.ipv4);
      79         765 :                 W_ERROR_HAVE_NO_MEMORY(ans[ai].rdata.ipv4_record);
      80         765 :                 break;
      81         636 :         case DNS_QTYPE_AAAA:
      82         636 :                 ans[ai].rdata.ipv6_record = talloc_strdup(ans, rec->data.ipv6);
      83         636 :                 W_ERROR_HAVE_NO_MEMORY(ans[ai].rdata.ipv6_record);
      84         636 :                 break;
      85          75 :         case DNS_TYPE_NS:
      86          75 :                 ans[ai].rdata.ns_record = talloc_strdup(ans, rec->data.ns);
      87          75 :                 W_ERROR_HAVE_NO_MEMORY(ans[ai].rdata.ns_record);
      88          75 :                 break;
      89         990 :         case DNS_QTYPE_SRV:
      90         990 :                 ans[ai].rdata.srv_record.priority = rec->data.srv.wPriority;
      91         990 :                 ans[ai].rdata.srv_record.weight   = rec->data.srv.wWeight;
      92         990 :                 ans[ai].rdata.srv_record.port     = rec->data.srv.wPort;
      93        1980 :                 ans[ai].rdata.srv_record.target   = talloc_strdup(
      94         990 :                         ans, rec->data.srv.nameTarget);
      95         990 :                 W_ERROR_HAVE_NO_MEMORY(ans[ai].rdata.srv_record.target);
      96         990 :                 break;
      97        2629 :         case DNS_QTYPE_SOA:
      98        5258 :                 ans[ai].rdata.soa_record.mname   = talloc_strdup(
      99        2629 :                         ans, rec->data.soa.mname);
     100        2629 :                 W_ERROR_HAVE_NO_MEMORY(ans[ai].rdata.soa_record.mname);
     101        5258 :                 ans[ai].rdata.soa_record.rname   = talloc_strdup(
     102        2629 :                         ans, rec->data.soa.rname);
     103        2629 :                 W_ERROR_HAVE_NO_MEMORY(ans[ai].rdata.soa_record.rname);
     104        2629 :                 ans[ai].rdata.soa_record.serial  = rec->data.soa.serial;
     105        2629 :                 ans[ai].rdata.soa_record.refresh = rec->data.soa.refresh;
     106        2629 :                 ans[ai].rdata.soa_record.retry   = rec->data.soa.retry;
     107        2629 :                 ans[ai].rdata.soa_record.expire  = rec->data.soa.expire;
     108        2629 :                 ans[ai].rdata.soa_record.minimum = rec->data.soa.minimum;
     109        2629 :                 break;
     110           0 :         case DNS_QTYPE_PTR:
     111           0 :                 ans[ai].rdata.ptr_record = talloc_strdup(ans, rec->data.ptr);
     112           0 :                 W_ERROR_HAVE_NO_MEMORY(ans[ai].rdata.ptr_record);
     113           0 :                 break;
     114           2 :         case DNS_QTYPE_MX:
     115           2 :                 ans[ai].rdata.mx_record.preference = rec->data.mx.wPriority;
     116           4 :                 ans[ai].rdata.mx_record.exchange = talloc_strdup(
     117           2 :                         ans, rec->data.mx.nameTarget);
     118           2 :                 if (ans[ai].rdata.mx_record.exchange == NULL) {
     119           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     120             :                 }
     121           2 :                 break;
     122         293 :         case DNS_QTYPE_TXT:
     123         293 :                 ndr_err = ndr_dnsp_string_list_copy(ans,
     124             :                                                     &rec->data.txt,
     125         293 :                                                     &ans[ai].rdata.txt_record.txt);
     126         293 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     127           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     128             :                 }
     129         293 :                 break;
     130           0 :         default:
     131           0 :                 DEBUG(0, ("Got unhandled type %u query.\n", rec->wType));
     132           0 :                 return DNS_ERR(NOT_IMPLEMENTED);
     133             :         }
     134             : 
     135        5469 :         ans[ai].name = talloc_strdup(ans, name);
     136        5469 :         W_ERROR_HAVE_NO_MEMORY(ans[ai].name);
     137        5469 :         ans[ai].rr_type = (enum dns_qtype)rec->wType;
     138        5469 :         ans[ai].rr_class = DNS_QCLASS_IN;
     139        5469 :         ans[ai].ttl = rec->dwTtlSeconds;
     140        5469 :         ans[ai].length = UINT16_MAX;
     141             : 
     142        5469 :         *answers = ans;
     143             : 
     144        5469 :         return WERR_OK;
     145             : }
     146             : 
     147           8 : static WERROR add_dns_res_rec(struct dns_res_rec **pdst,
     148             :                               const struct dns_res_rec *src)
     149             : {
     150           8 :         struct dns_res_rec *dst = *pdst;
     151           8 :         uint16_t di = talloc_array_length(dst);
     152           0 :         enum ndr_err_code ndr_err;
     153             : 
     154           8 :         if (di == UINT16_MAX) {
     155           0 :                 return WERR_BUFFER_OVERFLOW;
     156             :         }
     157             : 
     158           8 :         dst = talloc_realloc(dst, dst, struct dns_res_rec, di+1);
     159           8 :         if (dst == NULL) {
     160           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     161             :         }
     162             : 
     163           8 :         ZERO_STRUCT(dst[di]);
     164             : 
     165          16 :         dst[di] = (struct dns_res_rec) {
     166           8 :                 .name = talloc_strdup(dst, src->name),
     167           8 :                 .rr_type = src->rr_type,
     168           8 :                 .rr_class = src->rr_class,
     169           8 :                 .ttl = src->ttl,
     170           8 :                 .length = src->length
     171             :         };
     172             : 
     173           8 :         if (dst[di].name == NULL) {
     174           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     175             :         }
     176             : 
     177           8 :         switch (src->rr_type) {
     178           8 :         case DNS_QTYPE_CNAME:
     179          16 :                 dst[di].rdata.cname_record = talloc_strdup(
     180           8 :                         dst, src->rdata.cname_record);
     181           8 :                 if (dst[di].rdata.cname_record == NULL) {
     182           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     183             :                 }
     184           8 :                 break;
     185           0 :         case DNS_QTYPE_A:
     186           0 :                 dst[di].rdata.ipv4_record = talloc_strdup(
     187           0 :                         dst, src->rdata.ipv4_record);
     188           0 :                 if (dst[di].rdata.ipv4_record == NULL) {
     189           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     190             :                 }
     191           0 :                 break;
     192           0 :         case DNS_QTYPE_AAAA:
     193           0 :                 dst[di].rdata.ipv6_record = talloc_strdup(
     194           0 :                         dst, src->rdata.ipv6_record);
     195           0 :                 if (dst[di].rdata.ipv6_record == NULL) {
     196           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     197             :                 }
     198           0 :                 break;
     199           0 :         case DNS_TYPE_NS:
     200           0 :                 dst[di].rdata.ns_record = talloc_strdup(
     201           0 :                         dst, src->rdata.ns_record);
     202           0 :                 if (dst[di].rdata.ns_record == NULL) {
     203           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     204             :                 }
     205           0 :                 break;
     206           0 :         case DNS_QTYPE_SRV:
     207           0 :                 dst[di].rdata.srv_record = (struct dns_srv_record) {
     208           0 :                         .priority = src->rdata.srv_record.priority,
     209           0 :                         .weight   = src->rdata.srv_record.weight,
     210           0 :                         .port     = src->rdata.srv_record.port,
     211           0 :                         .target   = talloc_strdup(
     212           0 :                                 dst, src->rdata.srv_record.target)
     213             :                 };
     214           0 :                 if (dst[di].rdata.srv_record.target == NULL) {
     215           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     216             :                 }
     217           0 :                 break;
     218           0 :         case DNS_QTYPE_SOA:
     219           0 :                 dst[di].rdata.soa_record = (struct dns_soa_record) {
     220           0 :                         .mname   = talloc_strdup(
     221           0 :                                 dst, src->rdata.soa_record.mname),
     222           0 :                         .rname   = talloc_strdup(
     223           0 :                                 dst, src->rdata.soa_record.rname),
     224           0 :                         .serial  = src->rdata.soa_record.serial,
     225           0 :                         .refresh = src->rdata.soa_record.refresh,
     226           0 :                         .retry   = src->rdata.soa_record.retry,
     227           0 :                         .expire  = src->rdata.soa_record.expire,
     228           0 :                         .minimum = src->rdata.soa_record.minimum
     229             :                 };
     230             : 
     231           0 :                 if ((dst[di].rdata.soa_record.mname == NULL) ||
     232           0 :                     (dst[di].rdata.soa_record.rname == NULL)) {
     233           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     234             :                 }
     235             : 
     236           0 :                 break;
     237           0 :         case DNS_QTYPE_PTR:
     238           0 :                 dst[di].rdata.ptr_record = talloc_strdup(
     239           0 :                         dst, src->rdata.ptr_record);
     240           0 :                 if (dst[di].rdata.ptr_record == NULL) {
     241           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     242             :                 }
     243           0 :                 break;
     244           0 :         case DNS_QTYPE_MX:
     245           0 :                 dst[di].rdata.mx_record = (struct dns_mx_record) {
     246           0 :                         .preference = src->rdata.mx_record.preference,
     247           0 :                         .exchange   = talloc_strdup(
     248           0 :                                 src, src->rdata.mx_record.exchange)
     249             :                 };
     250             : 
     251           0 :                 if (dst[di].rdata.mx_record.exchange == NULL) {
     252           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     253             :                 }
     254           0 :                 break;
     255           0 :         case DNS_QTYPE_TXT:
     256           0 :                 ndr_err = ndr_dnsp_string_list_copy(dst,
     257             :                                                     &src->rdata.txt_record.txt,
     258           0 :                                                     &dst[di].rdata.txt_record.txt);
     259           0 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     260           0 :                         return WERR_NOT_ENOUGH_MEMORY;
     261             :                 }
     262           0 :                 break;
     263           0 :         default:
     264           0 :                 DBG_WARNING("Got unhandled type %u query.\n", src->rr_type);
     265           0 :                 return DNS_ERR(NOT_IMPLEMENTED);
     266             :         }
     267             : 
     268           8 :         *pdst = dst;
     269             : 
     270           8 :         return WERR_OK;
     271             : }
     272             : 
     273             : struct ask_forwarder_state {
     274             :         struct dns_name_packet *reply;
     275             : };
     276             : 
     277             : static void ask_forwarder_done(struct tevent_req *subreq);
     278             : 
     279          38 : static struct tevent_req *ask_forwarder_send(
     280             :         TALLOC_CTX *mem_ctx, struct tevent_context *ev,
     281             :         const char *forwarder, struct dns_name_question *question)
     282             : {
     283           0 :         struct tevent_req *req, *subreq;
     284           0 :         struct ask_forwarder_state *state;
     285             : 
     286          38 :         req = tevent_req_create(mem_ctx, &state, struct ask_forwarder_state);
     287          38 :         if (req == NULL) {
     288           0 :                 return NULL;
     289             :         }
     290             : 
     291          38 :         subreq = dns_cli_request_send(state, ev, forwarder,
     292             :                                       question->name, question->question_class,
     293             :                                       question->question_type);
     294          38 :         if (tevent_req_nomem(subreq, req)) {
     295           0 :                 return tevent_req_post(req, ev);
     296             :         }
     297          38 :         tevent_req_set_callback(subreq, ask_forwarder_done, req);
     298          38 :         return req;
     299             : }
     300             : 
     301          38 : static void ask_forwarder_done(struct tevent_req *subreq)
     302             : {
     303          38 :         struct tevent_req *req = tevent_req_callback_data(
     304             :                 subreq, struct tevent_req);
     305          38 :         struct ask_forwarder_state *state = tevent_req_data(
     306             :                 req, struct ask_forwarder_state);
     307           0 :         int ret;
     308             : 
     309          38 :         ret = dns_cli_request_recv(subreq, state, &state->reply);
     310          38 :         TALLOC_FREE(subreq);
     311             : 
     312          38 :         if (ret != 0) {
     313          20 :                 tevent_req_werror(req, unix_to_werror(ret));
     314          20 :                 return;
     315             :         }
     316             : 
     317          18 :         tevent_req_done(req);
     318             : }
     319             : 
     320          38 : static WERROR ask_forwarder_recv(
     321             :         struct tevent_req *req, TALLOC_CTX *mem_ctx,
     322             :         struct dns_res_rec **answers, uint16_t *ancount,
     323             :         struct dns_res_rec **nsrecs, uint16_t *nscount,
     324             :         struct dns_res_rec **additional, uint16_t *arcount)
     325             : {
     326          38 :         struct ask_forwarder_state *state = tevent_req_data(
     327             :                 req, struct ask_forwarder_state);
     328          38 :         struct dns_name_packet *in_packet = state->reply;
     329           0 :         WERROR err;
     330             : 
     331          38 :         if (tevent_req_is_werror(req, &err)) {
     332          20 :                 return err;
     333             :         }
     334             : 
     335          18 :         *ancount = in_packet->ancount;
     336          18 :         *answers = talloc_move(mem_ctx, &in_packet->answers);
     337             : 
     338          18 :         *nscount = in_packet->nscount;
     339          18 :         *nsrecs = talloc_move(mem_ctx, &in_packet->nsrecs);
     340             : 
     341          18 :         *arcount = in_packet->arcount;
     342          18 :         *additional = talloc_move(mem_ctx, &in_packet->additional);
     343             : 
     344          18 :         return WERR_OK;
     345             : }
     346             : 
     347        2589 : static WERROR add_zone_authority_record(struct dns_server *dns,
     348             :                                         TALLOC_CTX *mem_ctx,
     349             :                                         const struct dns_name_question *question,
     350             :                                         struct dns_res_rec **nsrecs)
     351             : {
     352        2589 :         const char *zone = NULL;
     353           0 :         struct dnsp_DnssrvRpcRecord *recs;
     354        2589 :         struct dns_res_rec *ns = *nsrecs;
     355           0 :         uint16_t rec_count;
     356        2589 :         struct ldb_dn *dn = NULL;
     357           0 :         unsigned int ri;
     358           0 :         WERROR werror;
     359             : 
     360        2589 :         zone = dns_get_authoritative_zone(dns, question->name);
     361        2589 :         DEBUG(10, ("Creating zone authority record for '%s'\n", zone));
     362             : 
     363        2589 :         werror = dns_name2dn(dns, mem_ctx, zone, &dn);
     364        2589 :         if (!W_ERROR_IS_OK(werror)) {
     365           0 :                 return werror;
     366             :         }
     367             : 
     368        2589 :         werror = dns_lookup_records(dns, mem_ctx, dn, &recs, &rec_count);
     369        2589 :         if (!W_ERROR_IS_OK(werror)) {
     370           6 :                 return werror;
     371             :         }
     372             : 
     373       12575 :         for (ri = 0; ri < rec_count; ri++) {
     374        9992 :                 if (recs[ri].wType == DNS_TYPE_SOA) {
     375        2583 :                         werror = add_response_rr(zone, &recs[ri], &ns);
     376        2583 :                         if (!W_ERROR_IS_OK(werror)) {
     377           0 :                                 return werror;
     378             :                         }
     379             :                 }
     380             :         }
     381             : 
     382        2583 :         *nsrecs = ns;
     383             : 
     384        2583 :         return WERR_OK;
     385             : }
     386             : 
     387             : static struct tevent_req *handle_authoritative_send(
     388             :         TALLOC_CTX *mem_ctx, struct tevent_context *ev,
     389             :         struct dns_server *dns, const char *forwarder,
     390             :         struct dns_name_question *question,
     391             :         struct dns_res_rec **answers, struct dns_res_rec **nsrecs,
     392             :         size_t cname_depth);
     393             : static WERROR handle_authoritative_recv(struct tevent_req *req);
     394             : 
     395             : struct handle_dnsrpcrec_state {
     396             :         struct dns_res_rec **answers;
     397             :         struct dns_res_rec **nsrecs;
     398             : };
     399             : 
     400             : static void handle_dnsrpcrec_gotauth(struct tevent_req *subreq);
     401             : static void handle_dnsrpcrec_gotforwarded(struct tevent_req *subreq);
     402             : 
     403        4774 : static struct tevent_req *handle_dnsrpcrec_send(
     404             :         TALLOC_CTX *mem_ctx, struct tevent_context *ev,
     405             :         struct dns_server *dns, const char *forwarder,
     406             :         const struct dns_name_question *question,
     407             :         struct dnsp_DnssrvRpcRecord *rec,
     408             :         struct dns_res_rec **answers, struct dns_res_rec **nsrecs,
     409             :         size_t cname_depth)
     410             : {
     411           0 :         struct tevent_req *req, *subreq;
     412           0 :         struct handle_dnsrpcrec_state *state;
     413           0 :         struct dns_name_question *new_q;
     414           0 :         bool resolve_cname;
     415           0 :         WERROR werr;
     416             : 
     417        4774 :         req = tevent_req_create(mem_ctx, &state,
     418             :                                 struct handle_dnsrpcrec_state);
     419        4774 :         if (req == NULL) {
     420           0 :                 return NULL;
     421             :         }
     422        4774 :         state->answers = answers;
     423        4774 :         state->nsrecs = nsrecs;
     424             : 
     425        4774 :         if (cname_depth >= MAX_Q_RECURSION_DEPTH) {
     426           2 :                 tevent_req_done(req);
     427           2 :                 return tevent_req_post(req, ev);
     428             :         }
     429             : 
     430        4853 :         resolve_cname = ((rec->wType == DNS_TYPE_CNAME) &&
     431          81 :                          ((question->question_type == DNS_QTYPE_A) ||
     432          12 :                           (question->question_type == DNS_QTYPE_AAAA)));
     433             : 
     434        4772 :         if (!resolve_cname) {
     435        4703 :                 if ((question->question_type != DNS_QTYPE_ALL) &&
     436        4693 :                     (rec->wType !=
     437        4693 :                      (enum dns_record_type) question->question_type)) {
     438        1886 :                         tevent_req_done(req);
     439        1886 :                         return tevent_req_post(req, ev);
     440             :                 }
     441             : 
     442        2817 :                 werr = add_response_rr(question->name, rec, state->answers);
     443        2817 :                 if (tevent_req_werror(req, werr)) {
     444           0 :                         return tevent_req_post(req, ev);
     445             :                 }
     446             : 
     447        2817 :                 tevent_req_done(req);
     448        2817 :                 return tevent_req_post(req, ev);
     449             :         }
     450             : 
     451          69 :         werr = add_response_rr(question->name, rec, state->answers);
     452          69 :         if (tevent_req_werror(req, werr)) {
     453           0 :                 return tevent_req_post(req, ev);
     454             :         }
     455             : 
     456          69 :         new_q = talloc(state, struct dns_name_question);
     457          69 :         if (tevent_req_nomem(new_q, req)) {
     458           0 :                 return tevent_req_post(req, ev);
     459             :         }
     460             : 
     461          69 :         *new_q = (struct dns_name_question) {
     462          69 :                 .question_type = question->question_type,
     463          69 :                 .question_class = question->question_class,
     464          69 :                 .name = rec->data.cname
     465             :         };
     466             : 
     467          69 :         if (dns_authoritative_for_zone(dns, new_q->name)) {
     468          57 :                 subreq = handle_authoritative_send(
     469             :                         state, ev, dns, forwarder, new_q,
     470          57 :                         state->answers, state->nsrecs,
     471             :                         cname_depth + 1);
     472          57 :                 if (tevent_req_nomem(subreq, req)) {
     473           0 :                         return tevent_req_post(req, ev);
     474             :                 }
     475          57 :                 tevent_req_set_callback(subreq, handle_dnsrpcrec_gotauth, req);
     476          57 :                 return req;
     477             :         }
     478             : 
     479          12 :         subreq = ask_forwarder_send(state, ev, forwarder, new_q);
     480          12 :         if (tevent_req_nomem(subreq, req)) {
     481           0 :                 return tevent_req_post(req, ev);
     482             :         }
     483          12 :         tevent_req_set_callback(subreq, handle_dnsrpcrec_gotforwarded, req);
     484             : 
     485          12 :         return req;
     486             : }
     487             : 
     488          57 : static void handle_dnsrpcrec_gotauth(struct tevent_req *subreq)
     489             : {
     490          57 :         struct tevent_req *req = tevent_req_callback_data(
     491             :                 subreq, struct tevent_req);
     492           0 :         WERROR werr;
     493             : 
     494          57 :         werr = handle_authoritative_recv(subreq);
     495          57 :         TALLOC_FREE(subreq);
     496          57 :         if (tevent_req_werror(req, werr)) {
     497           2 :                 return;
     498             :         }
     499          55 :         tevent_req_done(req);
     500             : }
     501             : 
     502          12 : static void handle_dnsrpcrec_gotforwarded(struct tevent_req *subreq)
     503             : {
     504          12 :         struct tevent_req *req = tevent_req_callback_data(
     505             :                 subreq, struct tevent_req);
     506          12 :         struct handle_dnsrpcrec_state *state = tevent_req_data(
     507             :                 req, struct handle_dnsrpcrec_state);
     508           0 :         struct dns_res_rec *answers, *nsrecs, *additional;
     509          12 :         uint16_t ancount = 0;
     510          12 :         uint16_t nscount = 0;
     511          12 :         uint16_t arcount = 0;
     512           0 :         uint16_t i;
     513           0 :         WERROR werr;
     514             : 
     515          12 :         werr = ask_forwarder_recv(subreq, state, &answers, &ancount,
     516             :                                   &nsrecs, &nscount, &additional, &arcount);
     517          12 :         if (tevent_req_werror(req, werr)) {
     518           4 :                 return;
     519             :         }
     520             : 
     521          16 :         for (i=0; i<ancount; i++) {
     522           8 :                 werr = add_dns_res_rec(state->answers, &answers[i]);
     523           8 :                 if (tevent_req_werror(req, werr)) {
     524           0 :                         return;
     525             :                 }
     526             :         }
     527             : 
     528           8 :         for (i=0; i<nscount; i++) {
     529           0 :                 werr = add_dns_res_rec(state->nsrecs, &nsrecs[i]);
     530           0 :                 if (tevent_req_werror(req, werr)) {
     531           0 :                         return;
     532             :                 }
     533             :         }
     534             : 
     535           8 :         tevent_req_done(req);
     536             : }
     537             : 
     538        4774 : static WERROR handle_dnsrpcrec_recv(struct tevent_req *req)
     539             : {
     540        4774 :         return tevent_req_simple_recv_werror(req);
     541             : }
     542             : 
     543             : struct handle_authoritative_state {
     544             :         struct tevent_context *ev;
     545             :         struct dns_server *dns;
     546             :         struct dns_name_question *question;
     547             :         const char *forwarder;
     548             : 
     549             :         struct dnsp_DnssrvRpcRecord *recs;
     550             :         uint16_t rec_count;
     551             :         uint16_t recs_done;
     552             : 
     553             :         struct dns_res_rec **answers;
     554             :         struct dns_res_rec **nsrecs;
     555             : 
     556             :         size_t cname_depth;
     557             : };
     558             : 
     559             : static void handle_authoritative_done(struct tevent_req *subreq);
     560             : 
     561        2684 : static struct tevent_req *handle_authoritative_send(
     562             :         TALLOC_CTX *mem_ctx, struct tevent_context *ev,
     563             :         struct dns_server *dns, const char *forwarder,
     564             :         struct dns_name_question *question,
     565             :         struct dns_res_rec **answers, struct dns_res_rec **nsrecs,
     566             :         size_t cname_depth)
     567             : {
     568           0 :         struct tevent_req *req, *subreq;
     569           0 :         struct handle_authoritative_state *state;
     570        2684 :         struct ldb_dn *dn = NULL;
     571           0 :         WERROR werr;
     572             : 
     573        2684 :         req = tevent_req_create(mem_ctx, &state,
     574             :                                 struct handle_authoritative_state);
     575        2684 :         if (req == NULL) {
     576           0 :                 return NULL;
     577             :         }
     578        2684 :         state->ev = ev;
     579        2684 :         state->dns = dns;
     580        2684 :         state->question = question;
     581        2684 :         state->forwarder = forwarder;
     582        2684 :         state->answers = answers;
     583        2684 :         state->nsrecs = nsrecs;
     584        2684 :         state->cname_depth = cname_depth;
     585             : 
     586        2684 :         werr = dns_name2dn(dns, state, question->name, &dn);
     587        2684 :         if (tevent_req_werror(req, werr)) {
     588           0 :                 return tevent_req_post(req, ev);
     589             :         }
     590        2684 :         werr = dns_lookup_records_wildcard(dns, state, dn, &state->recs,
     591        2684 :                                            &state->rec_count);
     592        2684 :         TALLOC_FREE(dn);
     593        2684 :         if (tevent_req_werror(req, werr)) {
     594         146 :                 return tevent_req_post(req, ev);
     595             :         }
     596             : 
     597        2538 :         if (state->rec_count == 0) {
     598           0 :                 tevent_req_werror(req, DNS_ERR(NAME_ERROR));
     599           0 :                 return tevent_req_post(req, ev);
     600             :         }
     601             : 
     602        2538 :         subreq = handle_dnsrpcrec_send(
     603        2538 :                 state, state->ev, state->dns, state->forwarder,
     604        2538 :                 state->question, &state->recs[state->recs_done],
     605        2538 :                 state->answers, state->nsrecs,
     606        2538 :                 state->cname_depth);
     607        2538 :         if (tevent_req_nomem(subreq, req)) {
     608           0 :                 return tevent_req_post(req, ev);
     609             :         }
     610        2538 :         tevent_req_set_callback(subreq, handle_authoritative_done, req);
     611        2538 :         return req;
     612             : }
     613             : 
     614        4774 : static void handle_authoritative_done(struct tevent_req *subreq)
     615             : {
     616        4774 :         struct tevent_req *req = tevent_req_callback_data(
     617             :                 subreq, struct tevent_req);
     618        4774 :         struct handle_authoritative_state *state = tevent_req_data(
     619             :                 req, struct handle_authoritative_state);
     620           0 :         WERROR werr;
     621             : 
     622        4774 :         werr = handle_dnsrpcrec_recv(subreq);
     623        4774 :         TALLOC_FREE(subreq);
     624        4774 :         if (tevent_req_werror(req, werr)) {
     625        2538 :                 return;
     626             :         }
     627             : 
     628        4768 :         state->recs_done += 1;
     629             : 
     630        4768 :         if (state->recs_done == state->rec_count) {
     631        2532 :                 tevent_req_done(req);
     632        2532 :                 return;
     633             :         }
     634             : 
     635        2236 :         subreq = handle_dnsrpcrec_send(
     636             :                 state, state->ev, state->dns, state->forwarder,
     637        2236 :                 state->question, &state->recs[state->recs_done],
     638             :                 state->answers, state->nsrecs,
     639             :                 state->cname_depth);
     640        2236 :         if (tevent_req_nomem(subreq, req)) {
     641           0 :                 return;
     642             :         }
     643        2236 :         tevent_req_set_callback(subreq, handle_authoritative_done, req);
     644             : }
     645             : 
     646        2684 : static WERROR handle_authoritative_recv(struct tevent_req *req)
     647             : {
     648           0 :         WERROR werr;
     649             : 
     650        2684 :         if (tevent_req_is_werror(req, &werr)) {
     651         152 :                 return werr;
     652             :         }
     653             : 
     654        2532 :         return WERR_OK;
     655             : }
     656             : 
     657          68 : static NTSTATUS create_tkey(struct dns_server *dns,
     658             :                             const char* name,
     659             :                             const char* algorithm,
     660             :                             const struct tsocket_address *remote_address,
     661             :                             const struct tsocket_address *local_address,
     662             :                             struct dns_server_tkey **tkey)
     663             : {
     664           0 :         NTSTATUS status;
     665          68 :         struct dns_server_tkey_store *store = dns->tkeys;
     666          68 :         struct dns_server_tkey *k = talloc_zero(store, struct dns_server_tkey);
     667             : 
     668          68 :         if (k == NULL) {
     669           0 :                 return NT_STATUS_NO_MEMORY;
     670             :         }
     671             : 
     672          68 :         k->name = talloc_strdup(k, name);
     673             : 
     674          68 :         if (k->name  == NULL) {
     675           0 :                 return NT_STATUS_NO_MEMORY;
     676             :         }
     677             : 
     678          68 :         k->algorithm = talloc_strdup(k, algorithm);
     679          68 :         if (k->algorithm == NULL) {
     680           0 :                 return NT_STATUS_NO_MEMORY;
     681             :         }
     682             : 
     683             :         /*
     684             :          * We only allow SPNEGO/KRB5 currently
     685             :          * and rely on the backend to be RPC/IPC free.
     686             :          *
     687             :          * It allows gensec_update() not to block.
     688             :          */
     689          68 :         status = samba_server_gensec_krb5_start(k,
     690          68 :                                                 dns->task->event_ctx,
     691          68 :                                                 dns->task->msg_ctx,
     692          68 :                                                 dns->task->lp_ctx,
     693             :                                                 dns->server_credentials,
     694             :                                                 "dns",
     695             :                                                 &k->gensec);
     696          68 :         if (!NT_STATUS_IS_OK(status)) {
     697           0 :                 DEBUG(1, ("Failed to start GENSEC server code: %s\n", nt_errstr(status)));
     698           0 :                 *tkey = NULL;
     699           0 :                 return status;
     700             :         }
     701             : 
     702          68 :         gensec_want_feature(k->gensec, GENSEC_FEATURE_SIGN);
     703             : 
     704          68 :         status = gensec_set_remote_address(k->gensec,
     705             :                                            remote_address);
     706          68 :         if (!NT_STATUS_IS_OK(status)) {
     707           0 :                 DEBUG(1, ("Failed to set remote address into GENSEC: %s\n",
     708             :                           nt_errstr(status)));
     709           0 :                 *tkey = NULL;
     710           0 :                 return status;
     711             :         }
     712             : 
     713          68 :         status = gensec_set_local_address(k->gensec,
     714             :                                           local_address);
     715          68 :         if (!NT_STATUS_IS_OK(status)) {
     716           0 :                 DEBUG(1, ("Failed to set local address into GENSEC: %s\n",
     717             :                           nt_errstr(status)));
     718           0 :                 *tkey = NULL;
     719           0 :                 return status;
     720             :         }
     721             : 
     722          68 :         status = gensec_start_mech_by_oid(k->gensec, GENSEC_OID_SPNEGO);
     723             : 
     724          68 :         if (!NT_STATUS_IS_OK(status)) {
     725           0 :                 DEBUG(1, ("Failed to start GENSEC server code: %s\n",
     726             :                           nt_errstr(status)));
     727           0 :                 *tkey = NULL;
     728           0 :                 return status;
     729             :         }
     730             : 
     731          68 :         TALLOC_FREE(store->tkeys[store->next_idx]);
     732             : 
     733          68 :         store->tkeys[store->next_idx] = k;
     734          68 :         (store->next_idx)++;
     735          68 :         store->next_idx %= store->size;
     736             : 
     737          68 :         *tkey = k;
     738          68 :         return NT_STATUS_OK;
     739             : }
     740             : 
     741          68 : static NTSTATUS accept_gss_ticket(TALLOC_CTX *mem_ctx,
     742             :                                   struct dns_server *dns,
     743             :                                   struct dns_server_tkey *tkey,
     744             :                                   const DATA_BLOB *key,
     745             :                                   DATA_BLOB *reply,
     746             :                                   uint16_t *dns_auth_error)
     747             : {
     748           0 :         NTSTATUS status;
     749             : 
     750             :         /*
     751             :          * We use samba_server_gensec_krb5_start(),
     752             :          * which only allows SPNEGO/KRB5 currently
     753             :          * and makes sure the backend to be RPC/IPC free.
     754             :          *
     755             :          * See gensec_gssapi_update_internal() as
     756             :          * GENSEC_SERVER.
     757             :          *
     758             :          * It allows gensec_update() not to block.
     759             :          *
     760             :          * If that changes in future we need to use
     761             :          * gensec_update_send/recv here!
     762             :          */
     763          68 :         status = gensec_update(tkey->gensec, mem_ctx,
     764             :                                *key, reply);
     765             : 
     766          68 :         if (NT_STATUS_EQUAL(NT_STATUS_MORE_PROCESSING_REQUIRED, status)) {
     767           0 :                 *dns_auth_error = DNS_RCODE_OK;
     768           0 :                 return status;
     769             :         }
     770             : 
     771          68 :         if (NT_STATUS_IS_OK(status)) {
     772             : 
     773          68 :                 status = gensec_session_info(tkey->gensec, tkey, &tkey->session_info);
     774          68 :                 if (!NT_STATUS_IS_OK(status)) {
     775           0 :                         *dns_auth_error = DNS_RCODE_BADKEY;
     776           0 :                         return status;
     777             :                 }
     778          68 :                 *dns_auth_error = DNS_RCODE_OK;
     779             :         }
     780             : 
     781          68 :         return status;
     782             : }
     783             : 
     784          68 : static WERROR handle_tkey(struct dns_server *dns,
     785             :                           TALLOC_CTX *mem_ctx,
     786             :                           const struct dns_name_packet *in,
     787             :                           struct dns_request_state *state,
     788             :                           struct dns_res_rec **answers,
     789             :                           uint16_t *ancount)
     790             : {
     791          68 :         struct dns_res_rec *in_tkey = NULL;
     792           0 :         struct dns_res_rec *ret_tkey;
     793           0 :         uint16_t i;
     794             : 
     795          68 :         for (i = 0; i < in->arcount; i++) {
     796          68 :                 if (in->additional[i].rr_type == DNS_QTYPE_TKEY) {
     797          68 :                         in_tkey = &in->additional[i];
     798          68 :                         break;
     799             :                 }
     800             :         }
     801             : 
     802             :         /* If this is a TKEY query, it should have a TKEY RR.
     803             :          * Behaviour is not really specified in RFC 2930 or RFC 3645, but
     804             :          * FORMAT_ERROR seems to be what BIND uses .*/
     805          68 :         if (in_tkey == NULL) {
     806           0 :                 return DNS_ERR(FORMAT_ERROR);
     807             :         }
     808             : 
     809          68 :         ret_tkey = talloc_zero(mem_ctx, struct dns_res_rec);
     810          68 :         if (ret_tkey == NULL) {
     811           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     812             :         }
     813             : 
     814          68 :         ret_tkey->name = talloc_strdup(ret_tkey, in_tkey->name);
     815          68 :         if (ret_tkey->name == NULL) {
     816           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     817             :         }
     818             : 
     819          68 :         ret_tkey->rr_type = DNS_QTYPE_TKEY;
     820          68 :         ret_tkey->rr_class = DNS_QCLASS_ANY;
     821          68 :         ret_tkey->length = UINT16_MAX;
     822             : 
     823          68 :         ret_tkey->rdata.tkey_record.algorithm = talloc_strdup(ret_tkey,
     824             :                         in_tkey->rdata.tkey_record.algorithm);
     825          68 :         if (ret_tkey->rdata.tkey_record.algorithm  == NULL) {
     826           0 :                 return WERR_NOT_ENOUGH_MEMORY;
     827             :         }
     828             : 
     829          68 :         ret_tkey->rdata.tkey_record.inception = in_tkey->rdata.tkey_record.inception;
     830          68 :         ret_tkey->rdata.tkey_record.expiration = in_tkey->rdata.tkey_record.expiration;
     831          68 :         ret_tkey->rdata.tkey_record.mode = in_tkey->rdata.tkey_record.mode;
     832             : 
     833          68 :         switch (in_tkey->rdata.tkey_record.mode) {
     834           0 :         case DNS_TKEY_MODE_DH:
     835             :                 /* FIXME: According to RFC 2930, we MUST support this, but we don't.
     836             :                  * Still, claim it's a bad key instead of a bad mode */
     837           0 :                 ret_tkey->rdata.tkey_record.error = DNS_RCODE_BADKEY;
     838           0 :                 break;
     839          68 :         case DNS_TKEY_MODE_GSSAPI: {
     840           0 :                 NTSTATUS status;
     841           0 :                 struct dns_server_tkey *tkey;
     842           0 :                 DATA_BLOB key;
     843           0 :                 DATA_BLOB reply;
     844             : 
     845          68 :                 tkey = dns_find_tkey(dns->tkeys, in->questions[0].name);
     846          68 :                 if (tkey != NULL && tkey->complete) {
     847             :                         /* TODO: check if the key is still valid */
     848           0 :                         DEBUG(1, ("Rejecting tkey negotiation for already established key\n"));
     849           0 :                         ret_tkey->rdata.tkey_record.error = DNS_RCODE_BADNAME;
     850          68 :                         break;
     851             :                 }
     852             : 
     853          68 :                 if (tkey == NULL) {
     854          68 :                         status  = create_tkey(dns, in->questions[0].name,
     855             :                                               in_tkey->rdata.tkey_record.algorithm,
     856             :                                               state->remote_address,
     857             :                                               state->local_address,
     858             :                                               &tkey);
     859          68 :                         if (!NT_STATUS_IS_OK(status)) {
     860           0 :                                 ret_tkey->rdata.tkey_record.error = DNS_RCODE_BADKEY;
     861           0 :                                 return ntstatus_to_werror(status);
     862             :                         }
     863             :                 }
     864             : 
     865          68 :                 key.data = in_tkey->rdata.tkey_record.key_data;
     866          68 :                 key.length = in_tkey->rdata.tkey_record.key_size;
     867             : 
     868          68 :                 status = accept_gss_ticket(ret_tkey, dns, tkey, &key, &reply,
     869             :                                            &ret_tkey->rdata.tkey_record.error);
     870          68 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
     871           0 :                         DEBUG(1, ("More processing required\n"));
     872           0 :                         ret_tkey->rdata.tkey_record.error = DNS_RCODE_BADKEY;
     873          68 :                 } else if (NT_STATUS_IS_OK(status)) {
     874          68 :                         DBG_DEBUG("Tkey handshake completed\n");
     875          68 :                         ret_tkey->rdata.tkey_record.key_size = reply.length;
     876          68 :                         ret_tkey->rdata.tkey_record.key_data = talloc_memdup(ret_tkey,
     877             :                                                                 reply.data,
     878             :                                                                 reply.length);
     879          68 :                         if (ret_tkey->rdata.tkey_record.key_data == NULL) {
     880           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
     881             :                         }
     882          68 :                         state->sign = true;
     883          68 :                         state->key_name = talloc_strdup(state->mem_ctx, tkey->name);
     884          68 :                         if (state->key_name == NULL) {
     885           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
     886             :                         }
     887             :                 } else {
     888           0 :                         DEBUG(1, ("GSS key negotiation returned %s\n", nt_errstr(status)));
     889           0 :                         ret_tkey->rdata.tkey_record.error = DNS_RCODE_BADKEY;
     890             :                 }
     891             : 
     892          68 :                 break;
     893             :                 }
     894           0 :         case DNS_TKEY_MODE_DELETE:
     895             :                 /* TODO: implement me */
     896           0 :                 DEBUG(1, ("Should delete tkey here\n"));
     897           0 :                 ret_tkey->rdata.tkey_record.error = DNS_RCODE_OK;
     898           0 :                 break;
     899           0 :         case DNS_TKEY_MODE_NULL:
     900             :         case DNS_TKEY_MODE_SERVER:
     901             :         case DNS_TKEY_MODE_CLIENT:
     902             :         case DNS_TKEY_MODE_LAST:
     903             :                 /* We don't have to implement these, return a mode error */
     904           0 :                 ret_tkey->rdata.tkey_record.error = DNS_RCODE_BADMODE;
     905           0 :                 break;
     906           0 :         default:
     907           0 :                 DEBUG(1, ("Unsupported TKEY mode %d\n",
     908             :                       in_tkey->rdata.tkey_record.mode));
     909             :         }
     910             : 
     911          68 :         *answers = ret_tkey;
     912          68 :         *ancount = 1;
     913             : 
     914          68 :         return WERR_OK;
     915             : }
     916             : 
     917             : struct dns_server_process_query_state {
     918             :         struct tevent_context *ev;
     919             :         struct dns_server *dns;
     920             :         struct dns_name_question *question;
     921             : 
     922             :         struct dns_res_rec *answers;
     923             :         uint16_t ancount;
     924             :         struct dns_res_rec *nsrecs;
     925             :         uint16_t nscount;
     926             :         struct dns_res_rec *additional;
     927             :         uint16_t arcount;
     928             :         struct forwarder_string *forwarders;
     929             : };
     930             : 
     931             : static void dns_server_process_query_got_auth(struct tevent_req *subreq);
     932             : static void dns_server_process_query_got_response(struct tevent_req *subreq);
     933             : 
     934        2688 : struct tevent_req *dns_server_process_query_send(
     935             :         TALLOC_CTX *mem_ctx, struct tevent_context *ev,
     936             :         struct dns_server *dns, struct dns_request_state *req_state,
     937             :         const struct dns_name_packet *in)
     938             : {
     939           0 :         struct tevent_req *req, *subreq;
     940           0 :         struct dns_server_process_query_state *state;
     941        2688 :         const char **forwarders = NULL;
     942           0 :         unsigned int i;
     943             : 
     944        2688 :         req = tevent_req_create(mem_ctx, &state,
     945             :                                 struct dns_server_process_query_state);
     946        2688 :         if (req == NULL) {
     947           0 :                 return NULL;
     948             :         }
     949        2688 :         if (in->qdcount != 1) {
     950           4 :                 tevent_req_werror(req, DNS_ERR(FORMAT_ERROR));
     951           4 :                 return tevent_req_post(req, ev);
     952             :         }
     953             : 
     954             :         /* Windows returns NOT_IMPLEMENTED on this as well */
     955        2684 :         if (in->questions[0].question_class == DNS_QCLASS_NONE) {
     956           4 :                 tevent_req_werror(req, DNS_ERR(NOT_IMPLEMENTED));
     957           4 :                 return tevent_req_post(req, ev);
     958             :         }
     959             : 
     960        2680 :         if (in->questions[0].question_type == DNS_QTYPE_TKEY) {
     961           0 :                 WERROR err;
     962             : 
     963          68 :                 err = handle_tkey(dns, state, in, req_state,
     964          68 :                                   &state->answers, &state->ancount);
     965          68 :                 if (tevent_req_werror(req, err)) {
     966           0 :                         return tevent_req_post(req, ev);
     967             :                 }
     968          68 :                 tevent_req_done(req);
     969          68 :                 return tevent_req_post(req, ev);
     970             :         }
     971             : 
     972        2612 :         state->dns = dns;
     973        2612 :         state->ev = ev;
     974        2612 :         state->question = &in->questions[0];
     975             : 
     976        2612 :         forwarders = lpcfg_dns_forwarder(dns->task->lp_ctx);
     977        3088 :         for (i = 0; forwarders != NULL && forwarders[i] != NULL; i++) {
     978         476 :                 struct forwarder_string *f = talloc_zero(state,
     979             :                                                          struct forwarder_string);
     980         476 :                 f->forwarder = forwarders[i];
     981         476 :                 DLIST_ADD_END(state->forwarders, f);
     982             :         }
     983             : 
     984        2612 :         if (dns_authoritative_for_zone(dns, in->questions[0].name)) {
     985             : 
     986        2589 :                 req_state->flags |= DNS_FLAG_AUTHORITATIVE;
     987             : 
     988             :                 /*
     989             :                  * Initialize the response arrays, so that we can use
     990             :                  * them as their own talloc contexts when doing the
     991             :                  * realloc
     992             :                  */
     993        2589 :                 state->answers = talloc_array(state, struct dns_res_rec, 0);
     994        2589 :                 if (tevent_req_nomem(state->answers, req)) {
     995           0 :                         return tevent_req_post(req, ev);
     996             :                 }
     997        2589 :                 state->nsrecs = talloc_array(state, struct dns_res_rec, 0);
     998        2589 :                 if (tevent_req_nomem(state->nsrecs, req)) {
     999           0 :                         return tevent_req_post(req, ev);
    1000             :                 }
    1001             : 
    1002        2589 :                 subreq = handle_authoritative_send(
    1003             :                         state, ev, dns, (forwarders == NULL ? NULL : forwarders[0]),
    1004        2589 :                         &in->questions[0], &state->answers, &state->nsrecs,
    1005             :                         0); /* cname_depth */
    1006        2589 :                 if (tevent_req_nomem(subreq, req)) {
    1007           0 :                         return tevent_req_post(req, ev);
    1008             :                 }
    1009        2589 :                 tevent_req_set_callback(
    1010             :                         subreq, dns_server_process_query_got_auth, req);
    1011        2589 :                 return req;
    1012             :         }
    1013             : 
    1014          23 :         if ((req_state->flags & DNS_FLAG_RECURSION_DESIRED) &&
    1015          20 :             (req_state->flags & DNS_FLAG_RECURSION_AVAIL)) {
    1016          16 :                 DEBUG(5, ("Not authoritative for '%s', forwarding\n",
    1017             :                           in->questions[0].name));
    1018             : 
    1019          16 :                 subreq = ask_forwarder_send(state, ev,
    1020             :                                             (forwarders == NULL ? NULL : forwarders[0]),
    1021          16 :                                             &in->questions[0]);
    1022          16 :                 if (tevent_req_nomem(subreq, req)) {
    1023           0 :                         return tevent_req_post(req, ev);
    1024             :                 }
    1025          16 :                 tevent_req_set_callback(
    1026             :                         subreq, dns_server_process_query_got_response, req);
    1027          16 :                 return req;
    1028             :         }
    1029             : 
    1030           7 :         tevent_req_werror(req, DNS_ERR(NAME_ERROR));
    1031           7 :         return tevent_req_post(req, ev);
    1032             : }
    1033             : 
    1034          26 : static void dns_server_process_query_got_response(struct tevent_req *subreq)
    1035             : {
    1036          26 :         struct tevent_req *req = tevent_req_callback_data(
    1037             :                 subreq, struct tevent_req);
    1038          26 :         struct dns_server_process_query_state *state = tevent_req_data(
    1039             :                 req, struct dns_server_process_query_state);
    1040           0 :         WERROR werr;
    1041             : 
    1042          26 :         werr = ask_forwarder_recv(subreq, state,
    1043             :                                   &state->answers, &state->ancount,
    1044             :                                   &state->nsrecs, &state->nscount,
    1045             :                                   &state->additional, &state->arcount);
    1046          26 :         TALLOC_FREE(subreq);
    1047             : 
    1048             :         /* If you get an error, attempt a different forwarder */
    1049          26 :         if (!W_ERROR_IS_OK(werr)) {
    1050          16 :                 if (state->forwarders != NULL) {
    1051          16 :                         DLIST_REMOVE(state->forwarders, state->forwarders);
    1052             :                 }
    1053             : 
    1054             :                 /* If you have run out of forwarders, simply finish */
    1055          16 :                 if (state->forwarders == NULL) {
    1056           6 :                         tevent_req_werror(req, werr);
    1057          16 :                         return;
    1058             :                 }
    1059             : 
    1060          10 :                 DEBUG(5, ("DNS query returned %s, trying another forwarder.\n",
    1061             :                           win_errstr(werr)));
    1062          10 :                 subreq = ask_forwarder_send(state, state->ev,
    1063          10 :                                             state->forwarders->forwarder,
    1064             :                                             state->question);
    1065             : 
    1066          10 :                 if (tevent_req_nomem(subreq, req)) {
    1067           0 :                         return;
    1068             :                 }
    1069             : 
    1070          10 :                 tevent_req_set_callback(subreq,
    1071             :                                         dns_server_process_query_got_response,
    1072             :                                         req);
    1073          10 :                 return;
    1074             :         }
    1075             : 
    1076          10 :         tevent_req_done(req);
    1077             : }
    1078             : 
    1079        2627 : static void dns_server_process_query_got_auth(struct tevent_req *subreq)
    1080             : {
    1081        2627 :         struct tevent_req *req = tevent_req_callback_data(
    1082             :                 subreq, struct tevent_req);
    1083        2627 :         struct dns_server_process_query_state *state = tevent_req_data(
    1084             :                 req, struct dns_server_process_query_state);
    1085           0 :         WERROR werr;
    1086           0 :         WERROR werr2;
    1087             : 
    1088        2627 :         werr = handle_authoritative_recv(subreq);
    1089        2627 :         TALLOC_FREE(subreq);
    1090             : 
    1091             :         /* If you get an error, attempt a different forwarder */
    1092        2627 :         if (!W_ERROR_IS_OK(werr)) {
    1093         150 :                 if (state->forwarders != NULL) {
    1094          72 :                         DLIST_REMOVE(state->forwarders, state->forwarders);
    1095             :                 }
    1096             : 
    1097             :                 /* If you have run out of forwarders, simply finish */
    1098         150 :                 if (state->forwarders == NULL) {
    1099         112 :                         werr2 = add_zone_authority_record(state->dns,
    1100             :                                                           state,
    1101         112 :                                                           state->question,
    1102             :                                                           &state->nsrecs);
    1103         112 :                         if (tevent_req_werror(req, werr2)) {
    1104           6 :                                 DBG_WARNING("Failed to add SOA record: %s\n",
    1105             :                                             win_errstr(werr2));
    1106         150 :                                 return;
    1107             :                         }
    1108             : 
    1109         106 :                         state->ancount = talloc_array_length(state->answers);
    1110         106 :                         state->nscount = talloc_array_length(state->nsrecs);
    1111         106 :                         state->arcount = talloc_array_length(state->additional);
    1112             : 
    1113         106 :                         tevent_req_werror(req, werr);
    1114         106 :                         return;
    1115             :                 }
    1116             : 
    1117          38 :                 DEBUG(5, ("Error: %s, trying a different forwarder.\n",
    1118             :                           win_errstr(werr)));
    1119          38 :                 subreq = handle_authoritative_send(state, state->ev, state->dns,
    1120          38 :                                                    state->forwarders->forwarder,
    1121             :                                                    state->question, &state->answers,
    1122             :                                                    &state->nsrecs,
    1123             :                                                    0); /* cname_depth */
    1124             : 
    1125          38 :                 if (tevent_req_nomem(subreq, req)) {
    1126           0 :                         return;
    1127             :                 }
    1128             : 
    1129          38 :                 tevent_req_set_callback(subreq,
    1130             :                                         dns_server_process_query_got_auth,
    1131             :                                         req);
    1132          38 :                 return;
    1133             :         }
    1134             : 
    1135        2477 :         werr2 = add_zone_authority_record(state->dns,
    1136             :                                           state,
    1137        2477 :                                           state->question,
    1138             :                                           &state->nsrecs);
    1139        2477 :         if (tevent_req_werror(req, werr2)) {
    1140           0 :                 DBG_WARNING("Failed to add SOA record: %s\n",
    1141             :                                 win_errstr(werr2));
    1142           0 :                 return;
    1143             :         }
    1144             : 
    1145        2477 :         state->ancount = talloc_array_length(state->answers);
    1146        2477 :         state->nscount = talloc_array_length(state->nsrecs);
    1147        2477 :         state->arcount = talloc_array_length(state->additional);
    1148             : 
    1149        2477 :         tevent_req_done(req);
    1150             : }
    1151             : 
    1152        2688 : WERROR dns_server_process_query_recv(
    1153             :         struct tevent_req *req, TALLOC_CTX *mem_ctx,
    1154             :         struct dns_res_rec **answers,    uint16_t *ancount,
    1155             :         struct dns_res_rec **nsrecs,     uint16_t *nscount,
    1156             :         struct dns_res_rec **additional, uint16_t *arcount)
    1157             : {
    1158        2688 :         struct dns_server_process_query_state *state = tevent_req_data(
    1159             :                 req, struct dns_server_process_query_state);
    1160        2688 :         WERROR err = WERR_OK;
    1161             : 
    1162        2688 :         if (tevent_req_is_werror(req, &err)) {
    1163             : 
    1164         133 :                 if ((!W_ERROR_EQUAL(err, DNS_ERR(NAME_ERROR))) &&
    1165          20 :                     (!W_ERROR_EQUAL(err, WERR_DNS_ERROR_NAME_DOES_NOT_EXIST))) {
    1166          14 :                         return err;
    1167             :                 }
    1168             :         }
    1169        2674 :         *answers = talloc_move(mem_ctx, &state->answers);
    1170        2674 :         *ancount = state->ancount;
    1171        2674 :         *nsrecs = talloc_move(mem_ctx, &state->nsrecs);
    1172        2674 :         *nscount = state->nscount;
    1173        2674 :         *additional = talloc_move(mem_ctx, &state->additional);
    1174        2674 :         *arcount = state->arcount;
    1175        2674 :         return err;
    1176             : }

Generated by: LCOV version 1.14