The branch, v4-16-stable has been updated via a4763bd9d87 VERSION: Disable GIT_SNAPSHOT for the 4.16.0rc2 release. via 4c3863633d3 WHATSNEW: Add release notes for Samba 4.16.0rc2. via c278515c492 s3/rpc_server: install elasticsearch_mappings.json via b88d24e33b2 CVE-2021-44141: s3: smbd: Inside rename_internals_fsp(), we must use vfs_stat() for existence, not SMB_VFS_STAT(). via 239e915b8f7 CVE-2021-44141: s3: torture: Add a test samba3.blackbox.test_symlink_rename.SMB1.posix that shows we still leak target info across a SMB1+POSIX rename. via 86157b3c7bf CVE-2021-44141: s3: smbd: Fix a subtle bug in the error returns from filename_convert(). via f4202a0bccd CVE-2021-44141: s3: smbd: Inside check_reduced_name() ensure we return the correct error codes when failing symlinks. via 4106af6d620 CVE-2021-44141: s3: smbd: For SMB1+POSIX clients trying to open a symlink, always return NT_STATUS_OBJECT_NAME_NOT_FOUND. via b8da8b72205 CVE-2021-44141: s3: torture: Change expected error return for samba3.smbtorture_s3.plain.POSIX.smbtorture. via c6d70dad3a2 CVE-2021-44141: s3: torture: In test_smbclient_s3, change the error codes expected for test_widelinks() and test_nosymlinks() from ACCESS_DENIED to NT_STATUS_OBJECT_NAME_NOT_FOUND. via ea20599ff17 CVE-2021-44141: s3: torture: Add samba3.blackbox.test_symlink_traversal.SMB1.posix via e6ccaced533 CVE-2021-44141: s3: torture: Add samba3.blackbox.test_symlink_traversal.SMB1. via 1dcd818303b CVE-2021-44141: s3: torture: Add samba3.blackbox.test_symlink_traversal.SMB2. via ef822984360 CVE-2021-44142: libadouble: harden parsing code via 03c6ba0054b CVE-2021-44142: libadouble: add basic cmocka tests via 39eb60d97a4 CVE-2021-44142: libadouble: harden ad_unpack_xattrs() via 36f847861bc CVE-2021-44142: smbd: add Netatalk xattr used by vfs_fruit to the list of private Samba xattrs via 9d7dd721b81 CVE-2021-44142: libadouble: add defines for icon lengths via e4f18bfaec8 CVE-2022-0336: s4/dsdb/samldb: Don't return early when an SPN is re-added to an object via eaede91afd6 CVE-2022-0336: pytest: Add a test for an SPN conflict with a re-added SPN via 4d3054261df blackbox.ndrdump: fix test_ndrdump_fuzzed_NULL_struct_ntlmssp_CHALLENGE_MESSAGE test via 7734584c4fd librpc/ndr: let ndr_push_string() let s_len == 0 result in d_len = 0 via 9be924f907c s4:torture/ndr: demonstrate the ndr_push_string(STR_NOTERM|REMAINING) of "" is wrong via a55de23fb05 blackbox.ndrdump: adjust example files to the usage of dump_data_diff output. via c1bd0f0d5e3 ndrdump: make use of dump_data_file_diff() in order to show differences via 1538a574a22 lib/util: add dump_data_diff*() helpers via f1cbfdc43c8 blackbox.ndrdump: adjust example files to changed dump_data() output. via 8097c9b3885 lib/util: split out a dump_data_block16() helper via c4132ef482b printing/bgqd: Disable systemd notifications via 20f84f11651 dcesrv_core: wrap gensec_*() calls in [un]become_root() calls via 3fdc553c981 VERSION: Bump version up to 4.16.0rc2... from 401df670af4 VERSION: Disable GIT_SNAPSHOT for the Samba 4.16.0rc1 release.
https://git.samba.org/?p=samba.git;a=shortlog;h=v4-16-stable - Log ----------------------------------------------------------------- ----------------------------------------------------------------------- Summary of changes: VERSION | 2 +- WHATSNEW.txt | 30 +- lib/util/util.c | 203 +++++++---- lib/util/util.h | 28 ++ librpc/ndr/ndr_string.c | 5 +- librpc/rpc/dcesrv_auth.c | 5 + librpc/rpc/dcesrv_core.c | 18 + librpc/rpc/dcesrv_core.h | 2 + librpc/tools/ndrdump.c | 10 + python/samba/tests/blackbox/ndrdump.py | 19 +- python/samba/tests/ldap_spn.py | 7 + selftest/target/Samba3.pm | 2 +- selftest/tests.py | 2 + source3/lib/adouble.c | 136 ++++++- source3/lib/adouble.h | 2 + source3/lib/test_adouble.c | 389 +++++++++++++++++++++ source3/printing/samba-bgqd.c | 3 + source3/rpc_server/rpc_config.c | 2 + source3/rpc_server/rpc_worker.c | 2 + source3/rpc_server/wscript_build | 3 + source3/script/tests/test_smbclient_s3.sh | 10 +- .../script/tests/test_symlink_rename_smb1_posix.sh | 186 ++++++++++ .../script/tests/test_symlink_traversal_smb1.sh | 263 ++++++++++++++ .../tests/test_symlink_traversal_smb1_posix.sh | 270 ++++++++++++++ .../script/tests/test_symlink_traversal_smb2.sh | 263 ++++++++++++++ source3/selftest/ktest-krb5_ccache-2.txt | 4 +- source3/selftest/ktest-krb5_ccache-3.txt | 4 +- source3/selftest/tests.py | 20 ++ source3/smbd/filename.c | 36 ++ source3/smbd/open.c | 13 +- source3/smbd/reply.c | 2 +- source3/smbd/trans2.c | 2 + source3/smbd/vfs.c | 18 +- source3/torture/torture.c | 4 +- source3/wscript_build | 5 + source4/dsdb/samdb/ldb_modules/samldb.c | 3 +- .../tests/dns-decode_dns_name_packet-hex.txt | 2 +- .../librpc/tests/fuzzed_drsuapi_DsAddEntry_1.txt | 297 +++++++++++++++- .../librpc/tests/fuzzed_drsuapi_DsGetNCChanges.txt | 2 +- .../tests/fuzzed_drsuapi_DsReplicaAttribute.txt | 31 +- .../tests/fuzzed_ntlmssp-AUTHENTICATE_MESSAGE.txt | 33 ++ .../tests/fuzzed_ntlmssp-CHALLENGE_MESSAGE.txt | 52 ++- source4/librpc/tests/krb5pac_upn_dns_info_ex.txt | 61 ++++ .../krb5pac_upn_dns_info_ex_not_supported.txt | 69 ++++ source4/rpc_server/service_rpc.c | 10 + source4/torture/ndr/string.c | 30 +- 46 files changed, 2429 insertions(+), 131 deletions(-) create mode 100644 source3/lib/test_adouble.c create mode 100755 source3/script/tests/test_symlink_rename_smb1_posix.sh create mode 100755 source3/script/tests/test_symlink_traversal_smb1.sh create mode 100755 source3/script/tests/test_symlink_traversal_smb1_posix.sh create mode 100755 source3/script/tests/test_symlink_traversal_smb2.sh Changeset truncated at 500 lines: diff --git a/VERSION b/VERSION index ddecf60a1f0..3584323d925 100644 --- a/VERSION +++ b/VERSION @@ -87,7 +87,7 @@ SAMBA_VERSION_PRE_RELEASE= # e.g. SAMBA_VERSION_RC_RELEASE=1 # # -> "3.0.0rc1" # ######################################################## -SAMBA_VERSION_RC_RELEASE=1 +SAMBA_VERSION_RC_RELEASE=2 ######################################################## # To mark SVN snapshots this should be set to 'yes' # diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 71a8d9a103e..acf91910706 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -1,7 +1,7 @@ Release Announcements ===================== -This is the first release candidate of Samba 4.16. This is *not* +This is the second release candidate of Samba 4.16. This is *not* intended for production environments and is designed for testing purposes only. Please report any defects via the Samba bug reporting system at https://bugzilla.samba.org/. @@ -173,6 +173,34 @@ smb.conf changes rpc_server Removed rpc start on demand helpers Added true + +CHANGES SINCE 4.16.0rc1 +======================= + +o Jeremy Allison <j...@samba.org> + * BUG 14911: CVE-2021-44141: UNIX extensions in SMB1 disclose whether the + outside target of a symlink exists. + +o Ralph Boehme <s...@samba.org> + * BUG 14914: CVE-2021-44142: Out-of-Bound Read/Write on Samba vfs_fruit + module. + * BUG 14961: install elasticsearch_mappings.json + +o FeRD (Frank Dana) <ferd...@gmail.com> + * BUG 14947: samba-bgqd still notifying systemd, triggering log warnings + without NotifyAccess=all. + +o Stefan Metzmacher <me...@samba.org> + * BUG 14867: Printing no longer works on Windows 7 with 2021-10 monthly + rollup patch. + * BUG 14956: ndr_push_string() adds implicit termination for + STR_NOTERM|REMAINING empty strings. + +o Joseph Sutton <josephsut...@catalyst.net.nz> + * BUG 14950: CVE-2022-0336: Re-adding an SPN skips subsequent SPN conflict + checks. + + KNOWN ISSUES ============ diff --git a/lib/util/util.c b/lib/util/util.c index 7eee60b85cd..c066406d320 100644 --- a/lib/util/util.c +++ b/lib/util/util.c @@ -481,6 +481,48 @@ void print_asc(int level, const uint8_t *buf,int len) print_asc_cb(buf, len, debugadd_cb, &level); } +static void dump_data_block16(const char *prefix, size_t idx, + const uint8_t *buf, size_t len, + void (*cb)(const char *buf, void *private_data), + void *private_data) +{ + char tmp[16]; + size_t i; + + SMB_ASSERT(len >= 0 && len <= 16); + + snprintf(tmp, sizeof(tmp), "%s[%04zX]", prefix, idx); + cb(tmp, private_data); + + for (i=0; i<16; i++) { + if (i == 8) { + cb(" ", private_data); + } + if (i < len) { + snprintf(tmp, sizeof(tmp), " %02X", (int)buf[i]); + } else { + snprintf(tmp, sizeof(tmp), " "); + } + cb(tmp, private_data); + } + + cb(" ", private_data); + + if (len == 0) { + cb("EMPTY BLOCK\n", private_data); + return; + } + + for (i=0; i<len; i++) { + if (i == 8) { + cb(" ", private_data); + } + print_asc_cb(&buf[i], 1, cb, private_data); + } + + cb("\n", private_data); +} + /** * Write dump of binary data to a callback */ @@ -491,73 +533,30 @@ void dump_data_cb(const uint8_t *buf, int len, { int i=0; bool skipped = false; - char tmp[16]; if (len<=0) return; - for (i=0;i<len;) { - - if (i%16 == 0) { - if ((omit_zero_bytes == true) && - (i > 0) && - (len > i+16) && - all_zero(&buf[i], 16)) - { - i +=16; - continue; - } - - if (i<len) { - snprintf(tmp, sizeof(tmp), "[%04X] ", i); - cb(tmp, private_data); + for (i=0;i<len;i+=16) { + size_t remaining_len = len - i; + size_t this_len = MIN(remaining_len, 16); + const uint8_t *this_buf = &buf[i]; + + if ((omit_zero_bytes == true) && + (i > 0) && (remaining_len > 16) && + (this_len == 16) && all_zero(this_buf, 16)) + { + if (!skipped) { + cb("skipping zero buffer bytes\n", + private_data); + skipped = true; } + continue; } - snprintf(tmp, sizeof(tmp), "%02X ", (int)buf[i]); - cb(tmp, private_data); - i++; - if (i%8 == 0) { - cb(" ", private_data); - } - if (i%16 == 0) { - - print_asc_cb(&buf[i-16], 8, cb, private_data); - cb(" ", private_data); - print_asc_cb(&buf[i-8], 8, cb, private_data); - cb("\n", private_data); - - if ((omit_zero_bytes == true) && - (len > i+16) && - all_zero(&buf[i], 16)) { - if (!skipped) { - cb("skipping zero buffer bytes\n", - private_data); - skipped = true; - } - } - } + skipped = false; + dump_data_block16("", i, this_buf, this_len, + cb, private_data); } - - if (i%16) { - int n; - n = 16 - (i%16); - cb(" ", private_data); - if (n>8) { - cb(" ", private_data); - } - while (n--) { - cb(" ", private_data); - } - n = MIN(8,i%16); - print_asc_cb(&buf[i-(i%16)], n, cb, private_data); - cb(" ", private_data); - n = (i%16) - n; - if (n>0) { - print_asc_cb(&buf[i-n], n, cb, private_data); - } - cb("\n", private_data); - } - } /** @@ -615,6 +614,90 @@ void dump_data_file(const uint8_t *buf, int len, bool omit_zero_bytes, dump_data_cb(buf, len, omit_zero_bytes, fprintf_cb, f); } +/** + * Write dump of compared binary data to a callback + */ +void dump_data_diff_cb(const uint8_t *buf1, size_t len1, + const uint8_t *buf2, size_t len2, + bool omit_zero_bytes, + void (*cb)(const char *buf, void *private_data), + void *private_data) +{ + size_t len = MAX(len1, len2); + size_t i; + bool skipped = false; + + for (i=0; i<len; i+=16) { + size_t remaining_len = len - i; + size_t remaining_len1 = 0; + size_t this_len1 = 0; + const uint8_t *this_buf1 = NULL; + size_t remaining_len2 = 0; + size_t this_len2 = 0; + const uint8_t *this_buf2 = NULL; + + if (i < len1) { + remaining_len1 = len1 - i; + this_len1 = MIN(remaining_len1, 16); + this_buf1 = &buf1[i]; + } + if (i < len2) { + remaining_len2 = len2 - i; + this_len2 = MIN(remaining_len2, 16); + this_buf2 = &buf2[i]; + } + + if ((omit_zero_bytes == true) && + (i > 0) && (remaining_len > 16) && + (this_len1 == 16) && all_zero(this_buf1, 16) && + (this_len2 == 16) && all_zero(this_buf2, 16)) + { + if (!skipped) { + cb("skipping zero buffer bytes\n", + private_data); + skipped = true; + } + continue; + } + + skipped = false; + + if ((this_len1 == this_len2) && + (memcmp(this_buf1, this_buf2, this_len1) == 0)) + { + dump_data_block16(" ", i, this_buf1, this_len1, + cb, private_data); + continue; + } + + dump_data_block16("-", i, this_buf1, this_len1, + cb, private_data); + dump_data_block16("+", i, this_buf2, this_len2, + cb, private_data); + } +} + +_PUBLIC_ void dump_data_diff(int dbgc_class, int level, + bool omit_zero_bytes, + const uint8_t *buf1, size_t len1, + const uint8_t *buf2, size_t len2) +{ + struct debug_channel_level dcl = { dbgc_class, level }; + + if (!DEBUGLVLC(dbgc_class, level)) { + return; + } + dump_data_diff_cb(buf1, len1, buf2, len2, true, debugadd_channel_cb, &dcl); +} + +_PUBLIC_ void dump_data_file_diff(FILE *f, + bool omit_zero_bytes, + const uint8_t *buf1, size_t len1, + const uint8_t *buf2, size_t len2) +{ + dump_data_diff_cb(buf1, len1, buf2, len2, omit_zero_bytes, fprintf_cb, f); +} + /** malloc that aborts with smb_panic on fail or zero size. **/ diff --git a/lib/util/util.h b/lib/util/util.h index a7acad56880..072f0486234 100644 --- a/lib/util/util.h +++ b/lib/util/util.h @@ -51,4 +51,32 @@ _PUBLIC_ void dump_data(int level, const uint8_t *buf,int len); */ _PUBLIC_ void dump_data_dbgc(int dbgc_class, int level, const uint8_t *buf, int len); +/** + * Write dump of compared binary data to a callback + */ +void dump_data_diff_cb(const uint8_t *buf1, size_t len1, + const uint8_t *buf2, size_t len2, + bool omit_zero_bytes, + void (*cb)(const char *buf, void *private_data), + void *private_data); + +/** + * Write dump of compared binary data to the log file. + * + * The data is only written if the log level is at least level for + * debug class dbgc_class. + */ +_PUBLIC_ void dump_data_diff(int dbgc_class, int level, + bool omit_zero_bytes, + const uint8_t *buf1, size_t len1, + const uint8_t *buf2, size_t len2); + +/** + * Write dump of compared binary data to the given file handle + */ +_PUBLIC_ void dump_data_file_diff(FILE *f, + bool omit_zero_bytes, + const uint8_t *buf1, size_t len1, + const uint8_t *buf2, size_t len2); + #endif diff --git a/librpc/ndr/ndr_string.c b/librpc/ndr/ndr_string.c index b5421e99ff5..95b0366b791 100644 --- a/librpc/ndr/ndr_string.c +++ b/librpc/ndr/ndr_string.c @@ -236,7 +236,10 @@ _PUBLIC_ enum ndr_err_code ndr_push_string(struct ndr_push *ndr, int ndr_flags, s_len++; } - if (!do_convert) { + if (s_len == 0) { + d_len = 0; + dest = (uint8_t *)talloc_strdup(ndr, ""); + } else if (!do_convert) { d_len = s_len; dest = (uint8_t *)talloc_strndup(ndr, s, s_len); } else if (!convert_string_talloc(ndr, CH_UNIX, chset, s, s_len, diff --git a/librpc/rpc/dcesrv_auth.c b/librpc/rpc/dcesrv_auth.c index fec8df513a8..99d8e016216 100644 --- a/librpc/rpc/dcesrv_auth.c +++ b/librpc/rpc/dcesrv_auth.c @@ -130,11 +130,13 @@ static bool dcesrv_auth_prepare_gensec(struct dcesrv_call_state *call) auth->auth_level = call->in_auth_info.auth_level; auth->auth_context_id = call->in_auth_info.auth_context_id; + cb->auth.become_root(); status = cb->auth.gensec_prepare( auth, call, &auth->gensec_security, cb->auth.private_data); + cb->auth.unbecome_root(); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to call samba_server_gensec_start %s\n", nt_errstr(status))); @@ -329,6 +331,7 @@ bool dcesrv_auth_bind(struct dcesrv_call_state *call) NTSTATUS dcesrv_auth_complete(struct dcesrv_call_state *call, NTSTATUS status) { struct dcesrv_auth *auth = call->auth_state; + struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks; const char *pdu = "<unknown>"; switch (call->pkt.ptype) { @@ -359,9 +362,11 @@ NTSTATUS dcesrv_auth_complete(struct dcesrv_call_state *call, NTSTATUS status) return status; } + cb->auth.become_root(); status = gensec_session_info(auth->gensec_security, auth, &auth->session_info); + cb->auth.unbecome_root(); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to establish session_info: %s\n", nt_errstr(status))); diff --git a/librpc/rpc/dcesrv_core.c b/librpc/rpc/dcesrv_core.c index 015c7639a51..9fd71812905 100644 --- a/librpc/rpc/dcesrv_core.c +++ b/librpc/rpc/dcesrv_core.c @@ -970,6 +970,7 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call) struct dcerpc_binding *ep_2nd_description = NULL; const char *endpoint = NULL; struct dcesrv_auth *auth = call->auth_state; + struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks; struct dcerpc_ack_ctx *ack_ctx_list = NULL; struct dcerpc_ack_ctx *ack_features = NULL; struct tevent_req *subreq = NULL; @@ -1175,9 +1176,11 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call) return dcesrv_auth_reply(call); } + cb->auth.become_root(); subreq = gensec_update_send(call, call->event_ctx, auth->gensec_security, call->in_auth_info.credentials); + cb->auth.unbecome_root(); if (subreq == NULL) { return NT_STATUS_NO_MEMORY; } @@ -1192,10 +1195,13 @@ static void dcesrv_bind_done(struct tevent_req *subreq) tevent_req_callback_data(subreq, struct dcesrv_call_state); struct dcesrv_connection *conn = call->conn; + struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks; NTSTATUS status; + cb->auth.become_root(); status = gensec_update_recv(subreq, call, &call->out_auth_info->credentials); + cb->auth.unbecome_root(); TALLOC_FREE(subreq); status = dcesrv_auth_complete(call, status); @@ -1253,6 +1259,7 @@ static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call) { struct dcesrv_connection *conn = call->conn; struct dcesrv_auth *auth = call->auth_state; + struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks; struct tevent_req *subreq = NULL; NTSTATUS status; @@ -1297,9 +1304,11 @@ static NTSTATUS dcesrv_auth3(struct dcesrv_call_state *call) return NT_STATUS_OK; } + cb->auth.become_root(); subreq = gensec_update_send(call, call->event_ctx, auth->gensec_security, call->in_auth_info.credentials); + cb->auth.unbecome_root(); if (subreq == NULL) { return NT_STATUS_NO_MEMORY; } @@ -1315,10 +1324,13 @@ static void dcesrv_auth3_done(struct tevent_req *subreq) struct dcesrv_call_state); struct dcesrv_connection *conn = call->conn; struct dcesrv_auth *auth = call->auth_state; + struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks; NTSTATUS status; + cb->auth.become_root(); status = gensec_update_recv(subreq, call, &call->out_auth_info->credentials); + cb->auth.unbecome_root(); TALLOC_FREE(subreq); status = dcesrv_auth_complete(call, status); @@ -1587,6 +1599,7 @@ static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call) struct ncacn_packet *pkt = &call->ack_pkt; uint32_t extra_flags = 0; struct dcesrv_auth *auth = call->auth_state; + struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks; struct dcerpc_ack_ctx *ack_ctx_list = NULL; struct tevent_req *subreq = NULL; size_t i; @@ -1698,9 +1711,11 @@ static NTSTATUS dcesrv_alter(struct dcesrv_call_state *call) return dcesrv_auth_reply(call); } + cb->auth.become_root(); subreq = gensec_update_send(call, call->event_ctx, auth->gensec_security, call->in_auth_info.credentials); + cb->auth.unbecome_root(); if (subreq == NULL) { return NT_STATUS_NO_MEMORY; } @@ -1715,10 +1730,13 @@ static void dcesrv_alter_done(struct tevent_req *subreq) tevent_req_callback_data(subreq, struct dcesrv_call_state); struct dcesrv_connection *conn = call->conn; + struct dcesrv_context_callbacks *cb = call->conn->dce_ctx->callbacks; NTSTATUS status; + cb->auth.become_root(); status = gensec_update_recv(subreq, call, &call->out_auth_info->credentials); + cb->auth.unbecome_root(); TALLOC_FREE(subreq); status = dcesrv_auth_complete(call, status); diff --git a/librpc/rpc/dcesrv_core.h b/librpc/rpc/dcesrv_core.h index e8e87bcce94..69815b71f3d 100644 --- a/librpc/rpc/dcesrv_core.h +++ b/librpc/rpc/dcesrv_core.h @@ -392,6 +392,8 @@ struct dcesrv_context_callbacks { struct gensec_security **out, void *private_data); -- Samba Shared Repository