The branch, master has been updated via fc267567a07 printing: avoid crash in LPRng_time via 16c28b367d9 fuzz: add fuzz_parse_lpq_entry via 0cb833b32c8 fuzz: fix multiple comment headers via 6d216dc3654 dns update: zero flags and reserved via 9d3731cd168 dns_common_replace: do not leak via 7c298ee89f8 samba-tool: dns update rejects malformed addresses via e6e3dc8bd3a pydns: fix a comment in replace_by_dn() via b80f66f8035 ldb-samba: dns tombstone matching: constrict value length via 7a111c1f35e dns_server: free old zones when reloading via 54b9271eb5e s4/dns_common_replace: add comments about tombstones via 26bb958af80 dns_common_replace: comment in needs_add case via 602dd50b31d dns_common_replace: do logging in needs_add case via 7edeb5901b0 dnsserver_common: comments about record sorting via 3a4cb8679a3 py/dnsserver: TXTRecord copes with single strings via 6bd6b2e9f3b dnsserver/update: add a few comments via 6f9564425f4 dns update: emit warnings upon unexpected occurrances via 1741a0667bb dlz_bind9: insert missing words into error message via c84f7a0a641 dlz_bind9: fix a copy-pasted comment from 2458a20eaca s3: VFS: Update status of SMB_VFS_GETXATTR.
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit fc267567a072c9483bbcc5cc18e150244bc5376b Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Wed May 5 14:55:47 2021 +0000 printing: avoid crash in LPRng_time If the string is too shhort we don't want to atoi() whatever is beyond the end of it. Found using Honggfuzz and the fuzz_parse_lpq_entry fuzzer. Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> Autobuild-User(master): Andrew Bartlett <abart...@samba.org> Autobuild-Date(master): Mon Jul 5 05:07:13 UTC 2021 on sn-devel-184 commit 16c28b367d9edc760e62949f0eef34b8046ece75 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Tue Apr 6 23:11:32 2021 +1200 fuzz: add fuzz_parse_lpq_entry Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 0cb833b32c8bf9341da74ded6545d6674156c08e Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Fri May 14 15:05:05 2021 +1200 fuzz: fix multiple comment headers Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 6d216dc365463fbcc4927bfc988ba52c16eef4cf Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Wed May 26 15:01:36 2021 +1200 dns update: zero flags and reserved This is the observed behaviour on Windows. Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 9d3731cd1681ebcfee60422d428f076182e483d3 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Thu Apr 15 16:07:58 2021 +1200 dns_common_replace: do not leak Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 7c298ee89f8d3bcdeb8c4f1f951c524326191334 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Sun Jun 20 14:52:48 2021 +1200 samba-tool: dns update rejects malformed addresses Because neither filling out the struct will not necessarily tell you you got it wrong, and the RPC could succeed in setting an arbitrary wrong address (typically, an IPv6 address would set an A record to "255.255.255.255"). Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit e6e3dc8bd3ad5ce07b27cf2e5f61c43601827168 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Sun Jun 20 22:03:35 2021 +1200 pydns: fix a comment in replace_by_dn() Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit b80f66f803554d25352413c24889a5f8fadef6d3 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Mon Mar 29 13:03:45 2021 +1300 ldb-samba: dns tombstone matching: constrict value length We know the only values we want to see are uint32, ie < ~4 billion (and real values will be 7 digits for hundreds of years). We also know the caller (we have just checked) is a trusted system session which won't be padding the thing with spaces. But if they do, let's call them out. Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 7a111c1f35ee949d1f669fe7ea1394c6b3a52ee7 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Wed Mar 31 10:47:05 2021 +1300 dns_server: free old zones when reloading Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 54b9271eb5e90c214c7009778ab22d60f9ee88eb Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Fri Jun 18 15:31:42 2021 +1200 s4/dns_common_replace: add comments about tombstones Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 26bb958af80199eda54e84d6ae427385d1843052 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Sun Apr 11 11:58:25 2021 +1200 dns_common_replace: comment in needs_add case Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 602dd50b31daa754c3123a6adc2ccd36ca1875cc Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Fri Apr 9 22:50:24 2021 +1200 dns_common_replace: do logging in needs_add case The idiom is we return via goto exit. This was evidently missed from commit 7e2b71d8f7cf7ac72022e1b15c30fc30706e8375 Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 7edeb5901b0c1715b32e33dcfb1ee5920b8b24ac Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Thu Apr 1 14:24:23 2021 +1300 dnsserver_common: comments about record sorting Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 3a4cb8679a3e2834a1c87440a5acc2fddb0b8b92 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Wed May 19 15:43:14 2021 +1200 py/dnsserver: TXTRecord copes with single strings Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 6bd6b2e9f3b8633331037e5d6e5f1a9a4d387530 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Sun Apr 11 23:38:10 2021 +1200 dnsserver/update: add a few comments Really just signposts. Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 6f9564425f4b6796034c8db7974e70e33df054dc Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Wed Mar 31 14:23:36 2021 +1300 dns update: emit warnings upon unexpected occurrances Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit 1741a0667bb0a282ec51d57e130aa128aa750d1a Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Wed Mar 31 14:21:43 2021 +1300 dlz_bind9: insert missing words into error message Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> commit c84f7a0a6415afd3a2f407189bc716baa14b6765 Author: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Date: Tue Apr 13 06:34:23 2021 +1200 dlz_bind9: fix a copy-pasted comment Signed-off-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abart...@samba.org> ----------------------------------------------------------------------- Summary of changes: lib/fuzzing/fuzz_cli_credentials_parse_string.c | 2 +- lib/fuzzing/fuzz_dcerpc_parse_binding.c | 2 +- lib/fuzzing/fuzz_ldb_dn_explode.c | 2 +- lib/fuzzing/fuzz_ldb_ldif_read.c | 2 +- lib/fuzzing/fuzz_ldb_parse_binary_decode.c | 2 +- lib/fuzzing/fuzz_ndr_X.c | 2 +- ...fuzz_ldb_ldif_read.c => fuzz_parse_lpq_entry.c} | 63 ++++++++++++---------- lib/fuzzing/wscript_build | 5 ++ lib/ldb-samba/ldb_matching_rules.c | 10 ++-- python/samba/dnsserver.py | 2 + python/samba/netcmd/dns.py | 13 ++++- selftest/knownfail.d/dns-aging | 1 - selftest/knownfail.d/dnscmd | 1 - source3/printing/lpq_parse.c | 6 +++ source4/dns_server/dlz_bind9.c | 6 ++- source4/dns_server/dns_server.c | 2 +- source4/dns_server/dns_update.c | 36 +++++++++++-- source4/dns_server/dnsserver_common.c | 40 ++++++++++++-- source4/dns_server/pydns.c | 2 +- 19 files changed, 145 insertions(+), 54 deletions(-) copy lib/fuzzing/{fuzz_ldb_ldif_read.c => fuzz_parse_lpq_entry.c} (51%) delete mode 100644 selftest/knownfail.d/dnscmd Changeset truncated at 500 lines: diff --git a/lib/fuzzing/fuzz_cli_credentials_parse_string.c b/lib/fuzzing/fuzz_cli_credentials_parse_string.c index bac6ef27674..b71ef357309 100644 --- a/lib/fuzzing/fuzz_cli_credentials_parse_string.c +++ b/lib/fuzzing/fuzz_cli_credentials_parse_string.c @@ -1,5 +1,5 @@ /* - Fuzz NMB parse_packet + Fuzz cli_credentials_parse_string Copyright (C) Catalyst IT 2020 This program is free software; you can redistribute it and/or modify diff --git a/lib/fuzzing/fuzz_dcerpc_parse_binding.c b/lib/fuzzing/fuzz_dcerpc_parse_binding.c index b353066764b..6eb3c15454d 100644 --- a/lib/fuzzing/fuzz_dcerpc_parse_binding.c +++ b/lib/fuzzing/fuzz_dcerpc_parse_binding.c @@ -1,5 +1,5 @@ /* - Fuzz NMB parse_packet + Fuzz dcerpc_parse_binding Copyright (C) Catalyst IT 2020 This program is free software; you can redistribute it and/or modify diff --git a/lib/fuzzing/fuzz_ldb_dn_explode.c b/lib/fuzzing/fuzz_ldb_dn_explode.c index f2b200b46a8..e024212301b 100644 --- a/lib/fuzzing/fuzz_ldb_dn_explode.c +++ b/lib/fuzzing/fuzz_ldb_dn_explode.c @@ -1,5 +1,5 @@ /* - Fuzzing ldb_parse_control_from_string + Fuzzing ldb_dn_explode Copyright (C) Catalyst IT 2020 This program is free software; you can redistribute it and/or modify diff --git a/lib/fuzzing/fuzz_ldb_ldif_read.c b/lib/fuzzing/fuzz_ldb_ldif_read.c index 0700a851fb5..f44e1ea5c43 100644 --- a/lib/fuzzing/fuzz_ldb_ldif_read.c +++ b/lib/fuzzing/fuzz_ldb_ldif_read.c @@ -1,5 +1,5 @@ /* - Fuzzing ldb_parse_control_from_string + Fuzzing ldb_ldif_read_string Copyright (C) Catalyst IT 2020 This program is free software; you can redistribute it and/or modify diff --git a/lib/fuzzing/fuzz_ldb_parse_binary_decode.c b/lib/fuzzing/fuzz_ldb_parse_binary_decode.c index 734196e036d..feb26e28c82 100644 --- a/lib/fuzzing/fuzz_ldb_parse_binary_decode.c +++ b/lib/fuzzing/fuzz_ldb_parse_binary_decode.c @@ -1,5 +1,5 @@ /* - Fuzzing ldb_parse_control_from_string + Fuzzing ldb_binary_decode and ldb_binary_encode_string Copyright (C) Catalyst IT 2020 This program is free software; you can redistribute it and/or modify diff --git a/lib/fuzzing/fuzz_ndr_X.c b/lib/fuzzing/fuzz_ndr_X.c index bedefba8553..a3fb984451f 100644 --- a/lib/fuzzing/fuzz_ndr_X.c +++ b/lib/fuzzing/fuzz_ndr_X.c @@ -1,6 +1,6 @@ /* Unix SMB/CIFS implementation. - SMB torture tester + Fuzzer for pidl-generated NDR pipes. Copyright (C) Andrew Tridgell 2003 Copyright (C) Jelmer Vernooij 2006 Copyright (C) Andrew Bartlett 2019 diff --git a/lib/fuzzing/fuzz_ldb_ldif_read.c b/lib/fuzzing/fuzz_parse_lpq_entry.c similarity index 51% copy from lib/fuzzing/fuzz_ldb_ldif_read.c copy to lib/fuzzing/fuzz_parse_lpq_entry.c index 0700a851fb5..720cc9b51c0 100644 --- a/lib/fuzzing/fuzz_ldb_ldif_read.c +++ b/lib/fuzzing/fuzz_parse_lpq_entry.c @@ -1,6 +1,6 @@ /* - Fuzzing ldb_parse_control_from_string - Copyright (C) Catalyst IT 2020 + Fuzzing parse_lpq_entry + Copyright (C) Douglas Bagnall <dbagn...@samba.org> 2021 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -15,42 +15,51 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "includes.h" +#include "../../source3/include/includes.h" +#include "printing.h" #include "fuzzing/fuzzing.h" -#include "ldb_private.h" -#define MAX_LENGTH (2 * 1024 * 1024 - 1) -char buf[MAX_LENGTH + 1] = {0}; +int LLVMFuzzerInitialize(int *argc, char ***argv) +{ + return 0; +} + +#define MAX_LENGTH (1024 * 1024) +char line[MAX_LENGTH + 1]; int LLVMFuzzerTestOneInput(uint8_t *input, size_t len) { - struct ldb_ldif *ldif = NULL; - const char *s = NULL; - struct ldb_context *ldb = ldb_init(NULL, NULL); - if (ldb == NULL) { + enum printing_types printing_type; + print_queue_struct pq_buf = {0}; + print_status_struct status = {0}; + bool first; + unsigned x; + TALLOC_CTX *frame = NULL; + + if (len < 1 || len > MAX_LENGTH) { return 0; } - - if (len > MAX_LENGTH) { - len = MAX_LENGTH; - } - memcpy(buf, input, len); - buf[len] = 0; - s = buf; - ldif = ldb_ldif_read_string(ldb, &s); + x = input[0]; + input++; + len--; - if(ldif != NULL) { - ldb_ldif_write_string(ldb, ldb, ldif); - ldb_ldif_write_redacted_trace_string(ldb, ldb, ldif); - } - TALLOC_FREE(ldb); - return 0; -} + /* There are 14 types, default goes to bsd */ + printing_type = x & 15; + first = (x & 16) ? true : false; + memcpy(line, input, len); + line[len] = '\0'; -int LLVMFuzzerInitialize(int *argc, char ***argv) -{ + /* parse_lpq_bsd requires a stackframe */ + frame = talloc_stackframe(); + + parse_lpq_entry(printing_type, + line, + &pq_buf, /* out */ + &status, /* out */ + first); + talloc_free(frame); return 0; } diff --git a/lib/fuzzing/wscript_build b/lib/fuzzing/wscript_build index 1322d713d0b..82232e1a2bd 100644 --- a/lib/fuzzing/wscript_build +++ b/lib/fuzzing/wscript_build @@ -17,6 +17,11 @@ bld.SAMBA_BINARY('fuzz_tiniparser', deps='fuzzing tiniparser talloc afl-fuzz-main', fuzzer=True) +bld.SAMBA_BINARY('fuzz_parse_lpq_entry', + source='fuzz_parse_lpq_entry.c', + deps='fuzzing afl-fuzz-main smbd_base', + fuzzer=True) + bld.SAMBA_BINARY('fuzz_oLschema2ldif', source='fuzz_oLschema2ldif.c', deps='fuzzing oLschema2ldif-lib afl-fuzz-main', diff --git a/lib/ldb-samba/ldb_matching_rules.c b/lib/ldb-samba/ldb_matching_rules.c index 73d957df3d9..827f3920ae8 100644 --- a/lib/ldb-samba/ldb_matching_rules.c +++ b/lib/ldb-samba/ldb_matching_rules.c @@ -336,7 +336,9 @@ static int ldb_comparator_trans(struct ldb_context *ldb, * * This allows a search filter such as: * - * dnsRecord:1.3.6.1.4.1.7165.4.5.3:=131139216000000000 + * dnsRecord:1.3.6.1.4.1.7165.4.5.3:=3694869 + * + * where the value is a number of hours since the start of 1601. * * This allows the caller to find records that should become a DNS * tomestone, despite that information being deep within an NDR packed @@ -380,13 +382,13 @@ static int dsdb_match_for_dns_to_tombstone_time(struct ldb_context *ldb, return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; } - /* Just check we don't allow the caller to fill our stack */ - if (value_to_match->length >= 64) { + /* We only expect uint32_t <= 10 digits */ + if (value_to_match->length >= 12) { DBG_ERR("Invalid timestamp passed\n"); return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX; } else { int error = 0; - char s[65]; + char s[12]; memcpy(s, value_to_match->data, value_to_match->length); s[value_to_match->length] = 0; diff --git a/python/samba/dnsserver.py b/python/samba/dnsserver.py index 8453b442b50..0170dc23efb 100644 --- a/python/samba/dnsserver.py +++ b/python/samba/dnsserver.py @@ -241,6 +241,8 @@ class TXTRecord(dnsserver.DNS_RPC_RECORD): self.dwFlags = rank | node_flag self.dwSerial = serial self.dwTtlSeconds = ttl + if isinstance(slist, str): + slist = [slist] names = [] for s in slist: name = dnsserver.DNS_RPC_NAME() diff --git a/python/samba/netcmd/dns.py b/python/samba/netcmd/dns.py index a1b49cbaad2..e77a4de8162 100644 --- a/python/samba/netcmd/dns.py +++ b/python/samba/netcmd/dns.py @@ -19,7 +19,7 @@ import samba.getopt as options from samba import WERRORError from samba import werror from struct import pack -from socket import inet_ntop +from socket import inet_ntop, inet_pton from socket import AF_INET from socket import AF_INET6 import struct @@ -1124,9 +1124,18 @@ class cmd_update_record(Command): def run(self, server, zone, name, rtype, olddata, newdata, sambaopts=None, credopts=None, versionopts=None): - if rtype.upper() not in ('A', 'AAAA', 'PTR', 'CNAME', 'NS', 'MX', 'SOA', 'SRV', 'TXT'): + rtype = rtype.upper() + if rtype not in ('A', 'AAAA', 'PTR', 'CNAME', 'NS', 'MX', 'SOA', 'SRV', 'TXT'): raise CommandError('Updating record of type %s is not supported' % rtype) + try: + if rtype == 'A': + inet_pton(AF_INET, newdata) + elif rtype == 'AAAA': + inet_pton(AF_INET6, newdata) + except OSError as e: + raise CommandError(f"bad data for {rtype}: {e!r}") + record_type = dns_type_flag(rtype) rec = data_to_dns_record(record_type, newdata) diff --git a/selftest/knownfail.d/dns-aging b/selftest/knownfail.d/dns-aging index bff873cc1ca..dd6998d75d8 100644 --- a/selftest/knownfail.d/dns-aging +++ b/selftest/knownfail.d/dns-aging @@ -30,7 +30,6 @@ samba.tests.dns_aging.+test_dns_add_sibling_12_7_days_no_aging_touch samba.tests.dns_aging.+test_dns_add_sibling_2_7_days_aging samba.tests.dns_aging.+test_dns_add_sibling_2_7_days_aging_touch samba.tests.dns_aging.+test_dns_add_sibling_2_7_days_no_aging_touch -samba.tests.dns_aging.+test_add_update_dwFlags samba.tests.dns_aging.+test_add_update_dwSerial samba.tests.dns_aging.+test_add_update_dwSerial_2 samba.tests.dns_aging.+test_add_update_many diff --git a/selftest/knownfail.d/dnscmd b/selftest/knownfail.d/dnscmd deleted file mode 100644 index 5385997ab50..00000000000 --- a/selftest/knownfail.d/dnscmd +++ /dev/null @@ -1 +0,0 @@ -samba.tests.samba_tool.dnscmd.+test_update_invalid_type diff --git a/source3/printing/lpq_parse.c b/source3/printing/lpq_parse.c index f016707c088..335bc7f4e75 100644 --- a/source3/printing/lpq_parse.c +++ b/source3/printing/lpq_parse.c @@ -223,10 +223,16 @@ static time_t LPRng_time(char *time_string) } if ( atoi(time_string) < 24 ){ + if (strlen(time_string) < 7) { + return (time_t)-1; + } t->tm_hour = atoi(time_string); t->tm_min = atoi(time_string+3); t->tm_sec = atoi(time_string+6); } else { + if (strlen(time_string) < 18) { + return (time_t)-1; + } t->tm_year = atoi(time_string)-1900; t->tm_mon = atoi(time_string+5)-1; t->tm_mday = atoi(time_string+8); diff --git a/source4/dns_server/dlz_bind9.c b/source4/dns_server/dlz_bind9.c index 6f8a1f03de8..0bd55f1aac4 100644 --- a/source4/dns_server/dlz_bind9.c +++ b/source4/dns_server/dlz_bind9.c @@ -313,7 +313,7 @@ static bool b9_single_valued(enum dns_record_type dns_type) } /* - see if a DNS type is single valued + get a DNS_TYPE_* value from the corresponding string */ static bool b9_dns_type(const char *type, enum dns_record_type *dtype) { @@ -1945,7 +1945,9 @@ _PUBLIC_ isc_result_t dlz_addrdataset(const char *name, const char *rdatastr, vo } } if (i == UINT16_MAX) { - state->log(ISC_LOG_ERROR, "samba_dlz: failed to already %u dnsRecord values for %s", + state->log(ISC_LOG_ERROR, + "samba_dlz: failed to find record to modify, and " + "there are already %u dnsRecord values for %s", i, ldb_dn_get_linearized(dn)); talloc_free(rec); result = ISC_R_FAILURE; diff --git a/source4/dns_server/dns_server.c b/source4/dns_server/dns_server.c index cc3387904fe..7d5a884bd2e 100644 --- a/source4/dns_server/dns_server.c +++ b/source4/dns_server/dns_server.c @@ -754,7 +754,7 @@ static NTSTATUS dns_server_reload_zones(struct dns_server *dns) { NTSTATUS status; struct dns_server_zone *new_list = NULL; - struct dns_server_zone *old_list = NULL; + struct dns_server_zone *old_list = dns->zones; struct dns_server_zone *old_zone; status = dns_common_zones(dns->samdb, dns, NULL, &new_list); if (!NT_STATUS_IS_OK(status)) { diff --git a/source4/dns_server/dns_update.c b/source4/dns_server/dns_update.c index 10dfb1160d6..2d5f353671e 100644 --- a/source4/dns_server/dns_update.c +++ b/source4/dns_server/dns_update.c @@ -431,8 +431,18 @@ static WERROR handle_one_update(struct dns_server *dns, if (tombstoned) { /* * we need to keep the existing tombstone record - * and ignore it + * and ignore it. + * + * There *should* only be a single record of type TOMBSTONE, + * but we don't insist. */ + if (rcount != 1) { + DBG_WARNING("Tombstoned dnsNode has %u records, " + "expected 1\n", rcount); + if (DEBUGLVL(1)) { + NDR_PRINT_DEBUG(dns_res_rec, discard_const(update)); + } + } first = rcount; } @@ -519,11 +529,20 @@ static WERROR handle_one_update(struct dns_server *dns, mem_ctx, update, &recs[i], name_is_static); W_ERROR_NOT_OK_RETURN(werror); + /* + * There should only be one SOA, which we have already + * found and replaced. We now check for and tombstone + * any others. + */ for (i++; i < rcount; i++) { if (recs[i].wType != DNS_TYPE_SOA) { continue; } - + DBG_ERR("Duplicate SOA records found.\n"); + if (DEBUGLVL(0)) { + NDR_PRINT_DEBUG(dns_res_rec, + discard_const(update)); + } recs[i] = (struct dnsp_DnssrvRpcRecord) { .wType = DNS_TYPE_TOMBSTONE, }; @@ -535,7 +554,7 @@ static WERROR handle_one_update(struct dns_server *dns, return WERR_OK; } - + /* All but CNAME, SOA */ recs = talloc_realloc(mem_ctx, recs, struct dnsp_DnssrvRpcRecord, rcount+1); W_ERROR_HAVE_NO_MEMORY(recs); @@ -553,20 +572,26 @@ static WERROR handle_one_update(struct dns_server *dns, recs[i].wType = recs[rcount].wType; recs[i].dwTtlSeconds = recs[rcount].dwTtlSeconds; recs[i].rank = recs[rcount].rank; - + recs[i].dwReserved = 0; + recs[i].flags = 0; werror = dns_replace_records(dns, mem_ctx, dn, needs_add, recs, rcount); W_ERROR_NOT_OK_RETURN(werror); return WERR_OK; } - + /* we did not find a matching record. This is new. */ werror = dns_replace_records(dns, mem_ctx, dn, needs_add, recs, rcount+1); W_ERROR_NOT_OK_RETURN(werror); return WERR_OK; } else if (update->rr_class == DNS_QCLASS_ANY) { + /* + * Mass-deleting records by type, which we do by adding a + * tombstone with zero timestamp. dns_replace_records() will + * work out if the node as a whole needs tombstoning. + */ if (update->rr_type == DNS_QTYPE_ALL) { if (dns_name_equal(update->name, zone->name)) { for (i = first; i < rcount; i++) { @@ -616,6 +641,7 @@ static WERROR handle_one_update(struct dns_server *dns, return WERR_OK; } else if (update->rr_class == DNS_QCLASS_NONE) { + /* deleting individual records */ struct dnsp_DnssrvRpcRecord *del_rec; if (update->rr_type == DNS_QTYPE_SOA) { diff --git a/source4/dns_server/dnsserver_common.c b/source4/dns_server/dnsserver_common.c index 02f958b3c08..d1f896d6755 100644 --- a/source4/dns_server/dnsserver_common.c +++ b/source4/dns_server/dnsserver_common.c @@ -637,13 +637,16 @@ static int rec_cmp(const struct dnsp_DnssrvRpcRecord *r1, { if (r1->wType != r2->wType) { /* - * The records are sorted with higher types first + * The records are sorted with higher types first, + * which puts tombstones (type 0) last. */ return r2->wType - r1->wType; } - /* - * Then we need to sort from the oldest to newest timestamp + * Then we need to sort from the oldest to newest timestamp. + * + * Note that dwTimeStamp == 0 (never expiring) records come first, + * then the ones whose expiry is soonest. */ return r1->dwTimeStamp - r2->dwTimeStamp; } @@ -1009,6 +1012,25 @@ WERROR dns_common_replace(struct ldb_context *samdb, enum ndr_err_code ndr_err; if (records[i].wType == DNS_TYPE_TOMBSTONE) { + /* + * There are two things that could be going on here. + * + * 1. We use a tombstone with EntombedTime == 0 for + * passing deletion messages through the stack, and + * this is the place we filter them out to perform + * that deletion. + * + * 2. This node is tombstoned, with no records except + * for a single tombstone, and it is just waiting to + * disappear. In this case, unless the caller has + * added a record, rec_count should be 1, and + * el->num_values will end up at 0, and we will make + * no changes. But if the caller has added a record, + * we need to un-tombstone the node. + * + * It is not possible to add an explicit tombstone + * record. + */ if (records[i].data.EntombedTime != 0) { was_tombstoned = true; } @@ -1035,6 +1057,11 @@ WERROR dns_common_replace(struct ldb_context *samdb, } if (needs_add) { + /* + * This is a new dnsNode, which simplifies everything as we + * know there is nothing to delete or change. We add the + * records and get out. + */ if (el->num_values == 0) { werr = WERR_OK; goto exit; @@ -1052,11 +1079,15 @@ WERROR dns_common_replace(struct ldb_context *samdb, goto exit; } - return WERR_OK; + werr = WERR_OK; goto exit; } if (el->num_values == 0) { + /* + * We get here if there are no records or all the records were + * tombstones. + */ struct dnsp_DnssrvRpcRecord tbs; -- Samba Shared Repository