The branch, v4-12-test has been updated via 8d47600f110 VERSION: Bump version up to 4.12.5. via 05b8919c7c2 Merge tag 'samba-4.12.4' into v4-12-test via 6ecd05dfbc2 VERSION: Disable GIT_SNAPSHOT for the 4.12.4 release. via 86177f14ff9 WHATSNEW: Add release notes for Samba 4.12.4. via 565811f4f5f CVE-2020-10760 dsdb: Add tests for paged_results and VLV over the Global Catalog port via a6a3a9f59d4 CVE-2020-10760 dsdb: Ensure a proper talloc tree for saved controls via d7a32e815bf CVE-2020-14303: s4 nbt: fix busy loop on empty UDP packet via 795a25dc81b CVE-2020-14303 Ensure an empty packet will not DoS the NBT server via 3b98e807eb9 CVE-2020-10745: ndr/dns-utils: prepare for NBT compatibility via 0afc9f777a6 CVE-2020-10745: dns_util/push: forbid names longer than 255 bytes via a19660d1fea CVE-2020-10745: ndr_dns: do not allow consecutive dots via be20d15af13 CVE-2020-10745: ndr/dns_utils: correct a comment via a80dd6d1271 CVE-2020-10745: ndr_dns: move ndr_push_dns_string core into sharable function via ec640f93bc9 CVE-2020-10745: librpc/tests: cmocka tests of dns and ndr strings via 6e04e0b4944 CVE-2020-10745: pytests: hand-rolled invalid dns/nbt packet tests via 7cc5a5a35e9 ldb: Bump version to 2.1.4 via 9dd458956d7 CVE-2020-10730: lib ldb: Check if ldb_lock_backend_callback called twice via b2658b9432c CVE-2020-10730: s4 dsdb vlv_pagination: Prevent repeat call of ldb_module_done via c29319e91d0 CVE-2020-10730: s4 dsdb paged_results: Prevent repeat call of ldb_module_done via b1f72d2ce5e CVE-2020-10730: dsdb: Ban the combination of paged_results and VLV via 8103df54b18 CVE-2020-10730: dsdb: Fix crash when vlv and paged_results are combined via d6329e8ace7 CVE-2020-10730: selftest: Add test to show that VLV and paged_results are incompatible via 337f3e42841 CVE-2020-10730: vlv: Another workaround for mixing ASQ and VLV via 98a67d49137 CVE-2020-10730: selftest: Add test to confirm VLV interaction with ASQ via dd53faf4446 CVE-2020-10730: vlv: Do not re-ASQ search the results of an ASQ search with VLV via c61a5255d9e CVE-2020-10730: vlv: Use strcmp(), not strncmp() checking the NULL terminated control OIDs via 837ee4b1757 VERSION: Bump version up to 4.12.4... from 50badbae62f s3: msdfs: Fix missing struct stat return on msdfs links by doing an LSTAT call.
https://git.samba.org/?p=samba.git;a=shortlog;h=v4-12-test - Log ----------------------------------------------------------------- commit 8d47600f11065b85098ee4ffa59d7345f491aa1c Author: Karolin Seeger <ksee...@samba.org> Date: Thu Jul 2 11:05:41 2020 +0200 VERSION: Bump version up to 4.12.5. Signed-off-by: Karolin Seeger <ksee...@samba.org> commit 05b8919c7c2c21848feebd94d3cec5ad2162d440 Merge: 50badbae62f 6ecd05dfbc2 Author: Karolin Seeger <ksee...@samba.org> Date: Thu Jul 2 11:05:20 2020 +0200 Merge tag 'samba-4.12.4' into v4-12-test samba: tag release samba-4.12.4 ----------------------------------------------------------------------- Summary of changes: VERSION | 2 +- WHATSNEW.txt | 88 +++++++- lib/ldb/ABI/{ldb-2.0.5.sigs => ldb-2.1.4.sigs} | 0 ...pyldb-util-2.1.0.sigs => pyldb-util-2.1.4.sigs} | 0 lib/ldb/common/ldb.c | 9 +- lib/ldb/wscript | 2 +- libcli/nbt/nbtsocket.c | 17 +- librpc/ndr/ndr_dns.c | 80 +------ librpc/ndr/ndr_dns_utils.c | 134 ++++++++++++ librpc/ndr/ndr_dns_utils.h | 6 + librpc/ndr/ndr_nbt.c | 72 +------ librpc/tests/test_ndr_dns_nbt.c | 236 +++++++++++++++++++++ librpc/wscript_build | 13 +- python/samba/tests/dns_packet.py | 230 ++++++++++++++++++++ .../__init__.py => selftest/knownfail.d/dns_packet | 0 selftest/knownfail.d/vlv | 2 +- source4/dsdb/samdb/ldb_modules/paged_results.c | 65 +++++- source4/dsdb/samdb/ldb_modules/vlv_pagination.c | 102 +++++++-- source4/dsdb/tests/python/asq.py | 54 +++++ source4/dsdb/tests/python/vlv.py | 184 ++++++++++------ source4/selftest/tests.py | 12 ++ 21 files changed, 1073 insertions(+), 235 deletions(-) copy lib/ldb/ABI/{ldb-2.0.5.sigs => ldb-2.1.4.sigs} (100%) copy lib/ldb/ABI/{pyldb-util-2.1.0.sigs => pyldb-util-2.1.4.sigs} (100%) create mode 100644 librpc/ndr/ndr_dns_utils.c create mode 100644 librpc/ndr/ndr_dns_utils.h create mode 100644 librpc/tests/test_ndr_dns_nbt.c create mode 100644 python/samba/tests/dns_packet.py copy buildtools/wafsamba/__init__.py => selftest/knownfail.d/dns_packet (100%) Changeset truncated at 500 lines: diff --git a/VERSION b/VERSION index 1a2c925f3aa..4b0722b2dee 100644 --- a/VERSION +++ b/VERSION @@ -25,7 +25,7 @@ ######################################################## SAMBA_VERSION_MAJOR=4 SAMBA_VERSION_MINOR=12 -SAMBA_VERSION_RELEASE=4 +SAMBA_VERSION_RELEASE=5 ######################################################## # If a official release has a serious bug # diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 389bab85d38..d6b26d8dce5 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -1,3 +1,87 @@ + ============================== + Release Notes for Samba 4.12.4 + July 02, 2020 + ============================== + + +This is a security release in order to address the following defects: + +o CVE-2020-10730: NULL pointer de-reference and use-after-free in Samba AD DC + LDAP Server with ASQ, VLV and paged_results. +o CVE-2020-10745: Parsing and packing of NBT and DNS packets can consume + excessive CPU +o CVE-2020-10760: LDAP Use-after-free in Samba AD DC Global Catalog with + paged_results and VLV. +o CVE-2020-14303: Empty UDP packet DoS in Samba AD DC nbtd. + + +======= +Details +======= + +o CVE-2020-10730: + A client combining the 'ASQ' and 'VLV' LDAP controls can cause a NULL pointer + de-reference and further combinations with the LDAP paged_results feature can + give a use-after-free in Samba's AD DC LDAP server. + +o CVE-2020-10745: Parsing and packing of NBT and DNS packets can consume + excessive CPU. + +o CVE-2020-10760: + The use of the paged_results or VLV controls against the Global Catalog LDAP + server on the AD DC will cause a use-after-free. + +o CVE-2020-14303: + The AD DC NBT server in Samba 4.0 will enter a CPU spin and not process + further requests once it receives an empty (zero-length) UDP packet to + port 137. + +For more details, please refer to the security advisories. + + +Changes since 4.12.3 +-------------------- + +o Douglas Bagnall <douglas.bagn...@catalyst.net.nz> + * BUG 14378: CVE-2020-10745: Invalid DNS or NBT queries containing dots use + several seconds of CPU each. + +o Andrew Bartlett <abart...@samba.org> + * BUG 14364: CVE-2020-10730: NULL de-reference in AD DC LDAP server when ASQ + and VLV combined. + * BUG 14402: CVE-2020-10760: Fix use-after-free in AD DC Global Catalog LDAP + server with paged_result or VLV. + * BUG 14417: CVE-2020-14303: Fix endless loop from empty UDP packet sent to + AD DC nbt_server. + +o Gary Lockyer <g...@catalyst.net.nz> + * BUG 14364: CVE-2020-10730: NULL de-reference in AD DC LDAP server when ASQ + and VLV combined, ldb: Bump version to 2.1.4. + + +####################################### +Reporting bugs & Development Discussion +####################################### + +Please discuss this release on the samba-technical mailing list or by +joining the #samba-technical IRC channel on irc.freenode.net. + +If you do report problems then please try to send high quality +feedback. If you don't provide vital information to help us track down +the problem then you will probably be ignored. All bug reports should +be filed under the Samba 4.1 and newer product in the project's Bugzilla +database (https://bugzilla.samba.org/). + + +====================================================================== +== Our Code, Our Bugs, Our Responsibility. +== The Samba Team +====================================================================== + + +Release notes for older releases follow: +---------------------------------------- + ============================== Release Notes for Samba 4.12.3 May 19, 2020 @@ -80,8 +164,8 @@ database (https://bugzilla.samba.org/). ====================================================================== -Release notes for older releases follow: ----------------------------------------- +---------------------------------------------------------------------- + ============================== Release Notes for Samba 4.12.2 diff --git a/lib/ldb/ABI/ldb-2.0.5.sigs b/lib/ldb/ABI/ldb-2.1.4.sigs similarity index 100% copy from lib/ldb/ABI/ldb-2.0.5.sigs copy to lib/ldb/ABI/ldb-2.1.4.sigs diff --git a/lib/ldb/ABI/pyldb-util-2.1.0.sigs b/lib/ldb/ABI/pyldb-util-2.1.4.sigs similarity index 100% copy from lib/ldb/ABI/pyldb-util-2.1.0.sigs copy to lib/ldb/ABI/pyldb-util-2.1.4.sigs diff --git a/lib/ldb/common/ldb.c b/lib/ldb/common/ldb.c index 8c86dca45a1..0fec89a52a8 100644 --- a/lib/ldb/common/ldb.c +++ b/lib/ldb/common/ldb.c @@ -1018,6 +1018,13 @@ static int ldb_lock_backend_callback(struct ldb_request *req, struct ldb_db_lock_context *lock_context; int ret; + if (req->context == NULL) { + /* + * The usual way to get here is to ignore the return codes + * and continuing processing after an error. + */ + abort(); + } lock_context = talloc_get_type(req->context, struct ldb_db_lock_context); @@ -1032,7 +1039,7 @@ static int ldb_lock_backend_callback(struct ldb_request *req, * If this is a LDB_REPLY_DONE or an error, unlock the * DB by calling the destructor on this context */ - talloc_free(lock_context); + TALLOC_FREE(req->context); return ret; } diff --git a/lib/ldb/wscript b/lib/ldb/wscript index 526fe497c13..edc3343e827 100644 --- a/lib/ldb/wscript +++ b/lib/ldb/wscript @@ -1,7 +1,7 @@ #!/usr/bin/env python APPNAME = 'ldb' -VERSION = '2.1.3' +VERSION = '2.1.4' import sys, os diff --git a/libcli/nbt/nbtsocket.c b/libcli/nbt/nbtsocket.c index 38a2192fbcd..4c6c20d4fe2 100644 --- a/libcli/nbt/nbtsocket.c +++ b/libcli/nbt/nbtsocket.c @@ -167,8 +167,23 @@ static void nbt_name_socket_recv(struct nbt_name_socket *nbtsock) return; } + /* + * Given a zero length, data_blob_talloc() returns the + * NULL blob {NULL, 0}. + * + * We only want to error return here on a real out of memory condition + * (i.e. dsize != 0, so the UDP packet has data, but the return of the + * allocation failed, so blob.data==NULL). + * + * Given an actual zero length UDP packet having blob.data == NULL + * isn't an out of memory error condition, that's the defined semantics + * of data_blob_talloc() when asked for zero bytes. + * + * We still need to continue to do the zero-length socket_recvfrom() + * read in order to clear the "read pending" condition on the socket. + */ blob = data_blob_talloc(tmp_ctx, NULL, dsize); - if (blob.data == NULL) { + if (blob.data == NULL && dsize != 0) { talloc_free(tmp_ctx); return; } diff --git a/librpc/ndr/ndr_dns.c b/librpc/ndr/ndr_dns.c index d37c8cc2ece..966e0b59786 100644 --- a/librpc/ndr/ndr_dns.c +++ b/librpc/ndr/ndr_dns.c @@ -33,6 +33,7 @@ #include "librpc/gen_ndr/ndr_dnsp.h" #include "system/locale.h" #include "lib/util/util_net.h" +#include "ndr_dns_utils.h" /* don't allow an unlimited number of name components */ #define MAX_COMPONENTS 128 @@ -159,80 +160,11 @@ _PUBLIC_ enum ndr_err_code ndr_push_dns_string(struct ndr_push *ndr, int ndr_flags, const char *s) { - if (!(ndr_flags & NDR_SCALARS)) { - return NDR_ERR_SUCCESS; - } - - while (s && *s) { - enum ndr_err_code ndr_err; - char *compname; - size_t complen; - uint32_t offset; - - if (!(ndr->flags & LIBNDR_FLAG_NO_COMPRESSION)) { - /* see if we have pushed the remaining string already, - * if so we use a label pointer to this string - */ - ndr_err = ndr_token_retrieve_cmp_fn(&ndr->dns_string_list, s, - &offset, - (comparison_fn_t)strcmp, - false); - if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - uint8_t b[2]; - - if (offset > 0x3FFF) { - return ndr_push_error(ndr, NDR_ERR_STRING, - "offset for dns string " \ - "label pointer " \ - "%u[%08X] > 0x00003FFF", - offset, offset); - } - - b[0] = 0xC0 | (offset>>8); - b[1] = (offset & 0xFF); - - return ndr_push_bytes(ndr, b, 2); - } - } - - complen = strcspn(s, "."); - - /* we need to make sure the length fits into 6 bytes */ - if (complen > 0x3F) { - return ndr_push_error(ndr, NDR_ERR_STRING, - "component length %u[%08X] > " \ - "0x0000003F", - (unsigned)complen, - (unsigned)complen); - } - - compname = talloc_asprintf(ndr, "%c%*.*s", - (unsigned char)complen, - (unsigned char)complen, - (unsigned char)complen, s); - NDR_ERR_HAVE_NO_MEMORY(compname); - - /* remember the current component + the rest of the string - * so it can be reused later - */ - if (!(ndr->flags & LIBNDR_FLAG_NO_COMPRESSION)) { - NDR_CHECK(ndr_token_store(ndr, &ndr->dns_string_list, s, - ndr->offset)); - } - - /* push just this component into the blob */ - NDR_CHECK(ndr_push_bytes(ndr, (const uint8_t *)compname, - complen+1)); - talloc_free(compname); - - s += complen; - if (*s == '.') s++; - } - - /* if we reach the end of the string and have pushed the last component - * without using a label pointer, we need to terminate the string - */ - return ndr_push_bytes(ndr, (const uint8_t *)"", 1); + return ndr_push_dns_string_list(ndr, + &ndr->dns_string_list, + ndr_flags, + s, + false); } _PUBLIC_ enum ndr_err_code ndr_pull_dns_txt_record(struct ndr_pull *ndr, int ndr_flags, struct dns_txt_record *r) diff --git a/librpc/ndr/ndr_dns_utils.c b/librpc/ndr/ndr_dns_utils.c new file mode 100644 index 00000000000..325d9c68bea --- /dev/null +++ b/librpc/ndr/ndr_dns_utils.c @@ -0,0 +1,134 @@ +#include "includes.h" +#include "../librpc/ndr/libndr.h" +#include "ndr_dns_utils.h" + + +/** + push a dns/nbt string list to the wire +*/ +enum ndr_err_code ndr_push_dns_string_list(struct ndr_push *ndr, + struct ndr_token_list *string_list, + int ndr_flags, + const char *s, + bool is_nbt) +{ + const char *start = s; + bool use_compression; + size_t max_length; + if (is_nbt) { + use_compression = true; + /* + * Max length is longer in NBT/Wins, because Windows counts + * the semi-decompressed size of the netbios name (16 bytes) + * rather than the wire size of 32, which is what you'd expect + * if it followed RFC1002 (it uses the short form in + * [MS-WINSRA]). In other words the maximum size of the + * "scope" is 237, not 221. + * + * We make the size limit slightly larger than 255 + 16, + * because the 237 scope limit is already enforced in the + * winsserver code with a specific return value; bailing out + * here would muck with that. + */ + max_length = 274; + } else { + use_compression = !(ndr->flags & LIBNDR_FLAG_NO_COMPRESSION); + max_length = 255; + } + + if (!(ndr_flags & NDR_SCALARS)) { + return NDR_ERR_SUCCESS; + } + + while (s && *s) { + enum ndr_err_code ndr_err; + char *compname; + size_t complen; + uint32_t offset; + + if (use_compression) { + /* see if we have pushed the remaining string already, + * if so we use a label pointer to this string + */ + ndr_err = ndr_token_retrieve_cmp_fn(string_list, s, + &offset, + (comparison_fn_t)strcmp, + false); + if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + uint8_t b[2]; + + if (offset > 0x3FFF) { + return ndr_push_error(ndr, NDR_ERR_STRING, + "offset for dns string " \ + "label pointer " \ + "%u[%08X] > 0x00003FFF", + offset, offset); + } + + b[0] = 0xC0 | (offset>>8); + b[1] = (offset & 0xFF); + + return ndr_push_bytes(ndr, b, 2); + } + } + + complen = strcspn(s, "."); + + /* the length must fit into 6 bits (i.e. <= 63) */ + if (complen > 0x3F) { + return ndr_push_error(ndr, NDR_ERR_STRING, + "component length %u[%08X] > " \ + "0x0000003F", + (unsigned)complen, + (unsigned)complen); + } + + if (complen == 0 && s[complen] == '.') { + return ndr_push_error(ndr, NDR_ERR_STRING, + "component length is 0 " + "(consecutive dots)"); + } + + if (is_nbt && s[complen] == '.' && s[complen + 1] == '\0') { + /* nbt names are sometimes usernames, and we need to + * keep a trailing dot to ensure it is byte-identical, + * (not just semantically identical given DNS + * semantics). */ + complen++; + } + + compname = talloc_asprintf(ndr, "%c%*.*s", + (unsigned char)complen, + (unsigned char)complen, + (unsigned char)complen, s); + NDR_ERR_HAVE_NO_MEMORY(compname); + + /* remember the current component + the rest of the string + * so it can be reused later + */ + if (use_compression) { + NDR_CHECK(ndr_token_store(ndr, string_list, s, + ndr->offset)); + } + + /* push just this component into the blob */ + NDR_CHECK(ndr_push_bytes(ndr, (const uint8_t *)compname, + complen+1)); + talloc_free(compname); + + s += complen; + if (*s == '.') { + s++; + } + if (s - start > max_length) { + return ndr_push_error(ndr, NDR_ERR_STRING, + "name > %zu character long", + max_length); + } + } + + /* if we reach the end of the string and have pushed the last component + * without using a label pointer, we need to terminate the string + */ + return ndr_push_bytes(ndr, (const uint8_t *)"", 1); +} diff --git a/librpc/ndr/ndr_dns_utils.h b/librpc/ndr/ndr_dns_utils.h new file mode 100644 index 00000000000..71a65433bbb --- /dev/null +++ b/librpc/ndr/ndr_dns_utils.h @@ -0,0 +1,6 @@ + +enum ndr_err_code ndr_push_dns_string_list(struct ndr_push *ndr, + struct ndr_token_list *string_list, + int ndr_flags, + const char *s, + bool is_nbt); diff --git a/librpc/ndr/ndr_nbt.c b/librpc/ndr/ndr_nbt.c index b15dc5c06e5..8ed9f0a5f05 100644 --- a/librpc/ndr/ndr_nbt.c +++ b/librpc/ndr/ndr_nbt.c @@ -25,6 +25,8 @@ #include "includes.h" #include "../libcli/nbt/libnbt.h" #include "../libcli/netlogon/netlogon.h" +#include "ndr_dns_utils.h" + /* don't allow an unlimited number of name components */ #define MAX_COMPONENTS 128 @@ -141,71 +143,11 @@ _PUBLIC_ enum ndr_err_code ndr_pull_nbt_string(struct ndr_pull *ndr, int ndr_fla */ _PUBLIC_ enum ndr_err_code ndr_push_nbt_string(struct ndr_push *ndr, int ndr_flags, const char *s) { - if (!(ndr_flags & NDR_SCALARS)) { - return NDR_ERR_SUCCESS; - } - - while (s && *s) { - enum ndr_err_code ndr_err; - char *compname; - size_t complen; - uint32_t offset; - - /* see if we have pushed the remaining string already, - * if so we use a label pointer to this string - */ - ndr_err = ndr_token_retrieve_cmp_fn(&ndr->nbt_string_list, s, &offset, (comparison_fn_t)strcmp, false); - if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - uint8_t b[2]; - - if (offset > 0x3FFF) { - return ndr_push_error(ndr, NDR_ERR_STRING, - "offset for nbt string label pointer %u[%08X] > 0x00003FFF", - offset, offset); - } - - b[0] = 0xC0 | (offset>>8); - b[1] = (offset & 0xFF); - - return ndr_push_bytes(ndr, b, 2); - } - - complen = strcspn(s, "."); - - /* we need to make sure the length fits into 6 bytes */ - if (complen > 0x3F) { - return ndr_push_error(ndr, NDR_ERR_STRING, - "component length %u[%08X] > 0x0000003F", - (unsigned)complen, (unsigned)complen); - } - - if (s[complen] == '.' && s[complen+1] == '\0') { - complen++; -- Samba Shared Repository