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