Version in base suite: 4.17.9+dfsg-0+deb12u3 Base version: samba_4.17.9+dfsg-0+deb12u3 Target version: samba_4.17.10+dfsg-0+deb12u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/s/samba/samba_4.17.9+dfsg-0+deb12u3.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/s/samba/samba_4.17.10+dfsg-0+deb12u1.dsc VERSION | 2 WHATSNEW.txt | 77 +++ debian/changelog | 29 + debian/patches/fix-unsupported-netr_LogonGetCapabilities-l2.patch | 68 -- debian/patches/series | 1 librpc/idl/netlogon.idl | 1 python/samba/tests/blackbox/mdsearch.py | 8 python/samba/tests/dcerpc/mdssvc.py | 26 - selftest/target/Samba3.pm | 1 source3/rpc_client/cli_mdssvc.c | 191 ++++++- source3/rpc_client/cli_mdssvc_private.h | 4 source3/rpc_client/cli_mdssvc_util.c | 148 +++-- source3/rpc_client/cli_mdssvc_util.h | 4 source3/rpc_server/mdssvc/dalloc.c | 14 source3/rpc_server/mdssvc/marshalling.c | 45 + source3/rpc_server/mdssvc/marshalling.h | 9 source3/rpc_server/mdssvc/mdssvc.c | 140 +++-- source3/rpc_server/mdssvc/mdssvc.h | 7 source3/rpc_server/mdssvc/srv_mdssvc_nt.c | 32 - source3/rpc_server/netlogon/srv_netlog_nt.c | 29 + source3/rpcclient/cmd_spotlight.c | 48 - source3/selftest/tests.py | 2 source3/smbd/proto.h | 1 source3/smbd/smb1_signing.c | 10 source3/smbd/smb1_signing.h | 3 source3/smbd/smb2_negprot.c | 6 source3/smbd/smb2_signing.c | 23 source3/utils/ntlm_auth.c | 8 source3/winbindd/winbindd_pam_auth_crap.c | 31 - source4/rpc_server/netlogon/dcerpc_netlogon.c | 28 - source4/torture/rpc/mdssvc.c | 250 ++++++++-- source4/torture/rpc/netlogon.c | 77 +++ source4/torture/smb2/session.c | 64 ++ source4/torture/smb2/smb2.c | 1 34 files changed, 999 insertions(+), 389 deletions(-) diff -Nru samba-4.17.9+dfsg/VERSION samba-4.17.10+dfsg/VERSION --- samba-4.17.9+dfsg/VERSION 2023-07-06 13:42:43.012797400 +0000 +++ samba-4.17.10+dfsg/VERSION 2023-07-17 20:19:16.862757200 +0000 @@ -25,7 +25,7 @@ ######################################################## SAMBA_VERSION_MAJOR=4 SAMBA_VERSION_MINOR=17 -SAMBA_VERSION_RELEASE=9 +SAMBA_VERSION_RELEASE=10 ######################################################## # If a official release has a serious bug # diff -Nru samba-4.17.9+dfsg/WHATSNEW.txt samba-4.17.10+dfsg/WHATSNEW.txt --- samba-4.17.9+dfsg/WHATSNEW.txt 2023-07-06 13:42:43.012797400 +0000 +++ samba-4.17.10+dfsg/WHATSNEW.txt 2023-07-17 20:19:16.842757700 +0000 @@ -1,3 +1,77 @@ + =============================== + Release Notes for Samba 4.17.10 + July 19, 2023 + =============================== + + +This is a security release in order to address the following defects: + +o CVE-2022-2127: When winbind is used for NTLM authentication, a maliciously + crafted request can trigger an out-of-bounds read in winbind + and possibly crash it. + https://www.samba.org/samba/security/CVE-2022-2127.html + +o CVE-2023-3347: SMB2 packet signing is not enforced if an admin configured + "server signing = required" or for SMB2 connections to Domain + Controllers where SMB2 packet signing is mandatory. + https://www.samba.org/samba/security/CVE-2023-3347.html + +o CVE-2023-34966: An infinite loop bug in Samba's mdssvc RPC service for + Spotlight can be triggered by an unauthenticated attacker by + issuing a malformed RPC request. + https://www.samba.org/samba/security/CVE-2023-34966.html + +o CVE-2023-34967: Missing type validation in Samba's mdssvc RPC service for + Spotlight can be used by an unauthenticated attacker to + trigger a process crash in a shared RPC mdssvc worker process. + https://www.samba.org/samba/security/CVE-2023-34967.html + +o CVE-2023-34968: As part of the Spotlight protocol Samba discloses the server- + side absolute path of shares and files and directories in + search results. + https://www.samba.org/samba/security/CVE-2023-34968.html + + +Changes since 4.17.9 +-------------------- + +o Ralph Boehme + * BUG 15072: CVE-2022-2127. + * BUG 15340: CVE-2023-34966. + * BUG 15341: CVE-2023-34967. + * BUG 15388: CVE-2023-34968. + * BUG 15397: CVE-2023-3347. + +o Volker Lendecke + * BUG 15072: CVE-2022-2127. + +o Stefan Metzmacher + * BUG 15418: Secure channel faulty since Windows 10/11 update 07/2023. + + +####################################### +Reporting bugs & Development Discussion +####################################### + +Please discuss this release on the samba-technical mailing list or by +joining the #samba-technical:matrix.org matrix room, or +#samba-technical IRC channel on irc.libera.chat. + +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.17.9 July 06, 2023 @@ -55,8 +129,7 @@ ====================================================================== -Release notes for older releases follow: ----------------------------------------- +---------------------------------------------------------------------- ============================== Release Notes for Samba 4.17.8 May 11, 2023 diff -Nru samba-4.17.9+dfsg/debian/changelog samba-4.17.10+dfsg/debian/changelog --- samba-4.17.9+dfsg/debian/changelog 2023-07-14 09:34:30.000000000 +0000 +++ samba-4.17.10+dfsg/debian/changelog 2023-07-19 14:55:58.000000000 +0000 @@ -1,3 +1,32 @@ +samba (2:4.17.10+dfsg-0+deb12u1) bookworm-security; urgency=medium + + * new upstream stable/security release 4.17.10, including: + o CVE-2022-2127: When winbind is used for NTLM authentication, + a maliciously crafted request can trigger an out-of-bounds read + in winbind and possibly crash it. + https://www.samba.org/samba/security/CVE-2022-2127.html + o CVE-2023-3347: SMB2 packet signing is not enforced if an admin + configured "server signing = required" or for SMB2 connections to + Domain Controllers where SMB2 packet signing is mandatory. + https://www.samba.org/samba/security/CVE-2023-3347.html + o CVE-2023-34966: An infinite loop bug in Samba's mdssvc RPC service + for Spotlight can be triggered by an unauthenticated attacker by + issuing a malformed RPC request. + https://www.samba.org/samba/security/CVE-2023-34966.html + o CVE-2023-34967: Missing type validation in Samba's mdssvc RPC service + for Spotlight can be used by an unauthenticated attacker to trigger + a process crash in a shared RPC mdssvc worker process. + https://www.samba.org/samba/security/CVE-2023-34967.html + o CVE-2023-34968: As part of the Spotlight protocol Samba discloses + the server-side absolute path of shares and files and directories + in search results. + https://www.samba.org/samba/security/CVE-2023-34968.html + o BUG 15418: Secure channel faulty since Windows 10/11 update 07/2023. + https://bugzilla.samba.org/show_bug.cgi?id=15418 + (this has been patched in the previous upload; Closes: #1041043) + + -- Michael Tokarev Wed, 19 Jul 2023 17:55:58 +0300 + samba (2:4.17.9+dfsg-0+deb12u3) bookworm; urgency=medium * +fix-unsupported-netr_LogonGetCapabilities-l2.patch diff -Nru samba-4.17.9+dfsg/debian/patches/fix-unsupported-netr_LogonGetCapabilities-l2.patch samba-4.17.10+dfsg/debian/patches/fix-unsupported-netr_LogonGetCapabilities-l2.patch --- samba-4.17.9+dfsg/debian/patches/fix-unsupported-netr_LogonGetCapabilities-l2.patch 2023-07-14 09:33:32.000000000 +0000 +++ samba-4.17.10+dfsg/debian/patches/fix-unsupported-netr_LogonGetCapabilities-l2.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,68 +0,0 @@ -From af355243e55a4baf17126339eb66432d438c4f16 Mon Sep 17 00:00:00 2001 -From: Stefan Metzmacher -Date: Fri, 14 Jul 2023 10:20:05 +0200 -Subject: [PATCH] s3+s3/rpc_server: fix unsupported netr_LogonGetCapabilities - level 2 -Origin: upstream, https://bugzilla.samba.org/attachment.cgi?id=17983 - -BUG: https://bugzilla.samba.org/show_bug.cgi?id=15418 ---- - source3/rpc_server/netlogon/srv_netlog_nt.c | 9 +++++---- - source4/rpc_server/netlogon/dcerpc_netlogon.c | 8 ++++---- - 2 files changed, 9 insertions(+), 8 deletions(-) - -diff --git a/source3/rpc_server/netlogon/srv_netlog_nt.c b/source3/rpc_server/netlogon/srv_netlog_nt.c -index 3ba58e61206f..2018dc28eb67 100644 ---- a/source3/rpc_server/netlogon/srv_netlog_nt.c -+++ b/source3/rpc_server/netlogon/srv_netlog_nt.c -@@ -2284,6 +2284,11 @@ NTSTATUS _netr_LogonGetCapabilities(struct pipes_struct *p, - struct netlogon_creds_CredentialState *creds; - NTSTATUS status; - -+ if (r->in.query_level != 1) { -+ p->fault_state = DCERPC_NCA_S_FAULT_INVALID_TAG; -+ return NT_STATUS_NOT_SUPPORTED; -+ } -+ - become_root(); - status = dcesrv_netr_creds_server_step_check(p->dce_call, - p->mem_ctx, -@@ -2296,10 +2301,6 @@ NTSTATUS _netr_LogonGetCapabilities(struct pipes_struct *p, - return status; - } - -- if (r->in.query_level != 1) { -- return NT_STATUS_NOT_SUPPORTED; -- } -- - r->out.capabilities->server_capabilities = creds->negotiate_flags; - - return NT_STATUS_OK; -diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c -index 6ccba65d3bf0..c869a6d3c791 100644 ---- a/source4/rpc_server/netlogon/dcerpc_netlogon.c -+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c -@@ -2364,6 +2364,10 @@ static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_c - struct netlogon_creds_CredentialState *creds; - NTSTATUS status; - -+ if (r->in.query_level != 1) { -+ DCESRV_FAULT(DCERPC_NCA_S_FAULT_INVALID_TAG); -+ } -+ - status = dcesrv_netr_creds_server_step_check(dce_call, - mem_ctx, - r->in.computer_name, -@@ -2375,10 +2379,6 @@ static NTSTATUS dcesrv_netr_LogonGetCapabilities(struct dcesrv_call_state *dce_c - } - NT_STATUS_NOT_OK_RETURN(status); - -- if (r->in.query_level != 1) { -- return NT_STATUS_NOT_SUPPORTED; -- } -- - r->out.capabilities->server_capabilities = creds->negotiate_flags; - - return NT_STATUS_OK; --- -2.41.0 diff -Nru samba-4.17.9+dfsg/debian/patches/series samba-4.17.10+dfsg/debian/patches/series --- samba-4.17.9+dfsg/debian/patches/series 2023-07-14 09:33:32.000000000 +0000 +++ samba-4.17.10+dfsg/debian/patches/series 2023-07-19 14:55:58.000000000 +0000 @@ -24,4 +24,3 @@ meaningful-error-if-no-python3-markdown.patch ctdb-use-run-instead-of-var-run.patch heimdal-to-support-KEYRING-ccache.patch -fix-unsupported-netr_LogonGetCapabilities-l2.patch diff -Nru samba-4.17.9+dfsg/librpc/idl/netlogon.idl samba-4.17.10+dfsg/librpc/idl/netlogon.idl --- samba-4.17.9+dfsg/librpc/idl/netlogon.idl 2022-12-15 16:09:31.717236300 +0000 +++ samba-4.17.10+dfsg/librpc/idl/netlogon.idl 2023-07-17 08:28:30.078742700 +0000 @@ -1241,6 +1241,7 @@ /* Function 0x15 */ typedef [switch_type(uint32)] union { [case(1)] netr_NegotiateFlags server_capabilities; + [case(2)] netr_NegotiateFlags server_capabilities; } netr_Capabilities; NTSTATUS netr_LogonGetCapabilities( diff -Nru samba-4.17.9+dfsg/python/samba/tests/blackbox/mdsearch.py samba-4.17.10+dfsg/python/samba/tests/blackbox/mdsearch.py --- samba-4.17.9+dfsg/python/samba/tests/blackbox/mdsearch.py 2022-08-08 14:15:39.272191300 +0000 +++ samba-4.17.10+dfsg/python/samba/tests/blackbox/mdsearch.py 2023-07-14 13:15:01.033234400 +0000 @@ -76,10 +76,7 @@ self.t.start() time.sleep(1) - pipe = mdssvc.mdssvc('ncacn_np:fileserver[/pipe/mdssvc]', self.get_loadparm()) - conn = mdscli.conn(pipe, 'spotlight', '/foo') - self.sharepath = conn.sharepath() - conn.disconnect(pipe) + self.sharepath = os.environ["LOCAL_PATH"] for file in testfiles: f = open("%s/%s" % (self.sharepath, file), "w") @@ -126,5 +123,4 @@ output = self.check_output("mdsearch --configfile=%s -U %s%%%s fileserver spotlight '*==\"samba*\"'" % (config, username, password)) actual = output.decode('utf-8').splitlines() - expected = ["%s/%s" % (self.sharepath, file) for file in testfiles] - self.assertEqual(expected, actual) + self.assertEqual(testfiles, actual) diff -Nru samba-4.17.9+dfsg/python/samba/tests/dcerpc/mdssvc.py samba-4.17.10+dfsg/python/samba/tests/dcerpc/mdssvc.py --- samba-4.17.9+dfsg/python/samba/tests/dcerpc/mdssvc.py 2022-08-08 14:15:39.276191500 +0000 +++ samba-4.17.10+dfsg/python/samba/tests/dcerpc/mdssvc.py 2023-07-14 13:15:01.033234400 +0000 @@ -84,10 +84,11 @@ self.t = threading.Thread(target=MdssvcTests.http_server, args=(self,)) self.t.setDaemon(True) self.t.start() + self.sharepath = os.environ["LOCAL_PATH"] time.sleep(1) conn = mdscli.conn(self.pipe, 'spotlight', '/foo') - self.sharepath = conn.sharepath() + self.fakepath = conn.sharepath() conn.disconnect(self.pipe) for file in testfiles: @@ -105,12 +106,11 @@ self.server.serve_forever() def run_test(self, query, expect, json_in, json_out): - expect = [s.replace("%BASEPATH%", self.sharepath) for s in expect] self.server.json_in = json_in.replace("%BASEPATH%", self.sharepath) self.server.json_out = json_out.replace("%BASEPATH%", self.sharepath) self.conn = mdscli.conn(self.pipe, 'spotlight', '/foo') - search = self.conn.search(self.pipe, query, self.sharepath) + search = self.conn.search(self.pipe, query, self.fakepath) # Give it some time, the get_results() below returns immediately # what's available, so if we ask to soon, we might get back no results @@ -141,7 +141,7 @@ ] } }''' - exp_results = ["%BASEPATH%/foo", "%BASEPATH%/bar"] + exp_results = ["foo", "bar"] self.run_test('*=="samba*"', exp_results, exp_json_query, fake_json_response) def test_mdscli_search_escapes(self): @@ -181,14 +181,14 @@ } }''' exp_results = [ - r"%BASEPATH%/x+x", - r"%BASEPATH%/x*x", - r"%BASEPATH%/x=x", - r"%BASEPATH%/x'x", - r"%BASEPATH%/x?x", - r"%BASEPATH%/x x", - r"%BASEPATH%/x(x", - "%BASEPATH%/x\"x", - r"%BASEPATH%/x\x", + r"x+x", + r"x*x", + r"x=x", + r"x'x", + r"x?x", + r"x x", + r"x(x", + "x\"x", + r"x\x", ] self.run_test(sl_query, exp_results, exp_json_query, fake_json_response) diff -Nru samba-4.17.9+dfsg/selftest/target/Samba3.pm samba-4.17.10+dfsg/selftest/target/Samba3.pm --- samba-4.17.9+dfsg/selftest/target/Samba3.pm 2023-05-11 07:07:19.582420800 +0000 +++ samba-4.17.10+dfsg/selftest/target/Samba3.pm 2023-07-14 13:15:04.449269500 +0000 @@ -1294,6 +1294,7 @@ # values required for tests to succeed create krb5 conf = no map to guest = bad user + server signing = required "; my $ret = $self->provision( diff -Nru samba-4.17.9+dfsg/source3/rpc_client/cli_mdssvc.c samba-4.17.10+dfsg/source3/rpc_client/cli_mdssvc.c --- samba-4.17.9+dfsg/source3/rpc_client/cli_mdssvc.c 2022-08-08 14:15:39.436192500 +0000 +++ samba-4.17.10+dfsg/source3/rpc_client/cli_mdssvc.c 2023-07-14 13:15:01.033234400 +0000 @@ -43,10 +43,12 @@ struct mdscli_connect_state { struct tevent_context *ev; struct mdscli_ctx *mdscli_ctx; + struct mdssvc_blob response_blob; }; static void mdscli_connect_open_done(struct tevent_req *subreq); static void mdscli_connect_unknown1_done(struct tevent_req *subreq); +static void mdscli_connect_fetch_props_done(struct tevent_req *subreq); struct tevent_req *mdscli_connect_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, @@ -111,6 +113,7 @@ struct mdscli_connect_state *state = tevent_req_data( req, struct mdscli_connect_state); struct mdscli_ctx *mdscli_ctx = state->mdscli_ctx; + size_t share_path_len; NTSTATUS status; status = dcerpc_mdssvc_open_recv(subreq, state); @@ -120,6 +123,18 @@ return; } + share_path_len = strlen(mdscli_ctx->mdscmd_open.share_path); + if (share_path_len < 1 || share_path_len > UINT16_MAX) { + tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); + return; + } + mdscli_ctx->mdscmd_open.share_path_len = share_path_len; + + if (mdscli_ctx->mdscmd_open.share_path[share_path_len-1] == '/') { + mdscli_ctx->mdscmd_open.share_path[share_path_len-1] = '\0'; + mdscli_ctx->mdscmd_open.share_path_len--; + } + subreq = dcerpc_mdssvc_unknown1_send( state, state->ev, @@ -146,6 +161,8 @@ subreq, struct tevent_req); struct mdscli_connect_state *state = tevent_req_data( req, struct mdscli_connect_state); + struct mdscli_ctx *mdscli_ctx = state->mdscli_ctx; + struct mdssvc_blob request_blob; NTSTATUS status; status = dcerpc_mdssvc_unknown1_recv(subreq, state); @@ -154,6 +171,108 @@ return; } + status = mdscli_blob_fetch_props(state, + state->mdscli_ctx, + &request_blob); + if (tevent_req_nterror(req, status)) { + return; + } + + subreq = dcerpc_mdssvc_cmd_send(state, + state->ev, + mdscli_ctx->bh, + &mdscli_ctx->ph, + 0, + mdscli_ctx->dev, + mdscli_ctx->mdscmd_open.unkn2, + 0, + mdscli_ctx->flags, + request_blob, + 0, + mdscli_ctx->max_fragment_size, + 1, + mdscli_ctx->max_fragment_size, + 0, + 0, + &mdscli_ctx->mdscmd_cmd.fragment, + &state->response_blob, + &mdscli_ctx->mdscmd_cmd.unkn9); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, mdscli_connect_fetch_props_done, req); + mdscli_ctx->async_pending++; + return; +} + +static void mdscli_connect_fetch_props_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct mdscli_connect_state *state = tevent_req_data( + req, struct mdscli_connect_state); + struct mdscli_ctx *mdscli_ctx = state->mdscli_ctx; + DALLOC_CTX *d = NULL; + sl_array_t *path_scope_array = NULL; + char *path_scope = NULL; + NTSTATUS status; + bool ok; + + status = dcerpc_mdssvc_cmd_recv(subreq, state); + TALLOC_FREE(subreq); + state->mdscli_ctx->async_pending--; + if (tevent_req_nterror(req, status)) { + return; + } + + d = dalloc_new(state); + if (tevent_req_nomem(d, req)) { + return; + } + + ok = sl_unpack(d, + (char *)state->response_blob.spotlight_blob, + state->response_blob.length); + if (!ok) { + tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); + return; + } + + path_scope_array = dalloc_value_for_key(d, + "DALLOC_CTX", 0, + "kMDSStorePathScopes", + "sl_array_t"); + if (path_scope_array == NULL) { + DBG_ERR("Missing kMDSStorePathScopes\n"); + tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); + return; + } + + path_scope = dalloc_get(path_scope_array, "char *", 0); + if (path_scope == NULL) { + DBG_ERR("Missing path in kMDSStorePathScopes\n"); + tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); + return; + } + + mdscli_ctx->path_scope_len = strlen(path_scope); + if (mdscli_ctx->path_scope_len < 1 || + mdscli_ctx->path_scope_len > UINT16_MAX) + { + DBG_ERR("Bad path_scope: %s\n", path_scope); + tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); + return; + } + mdscli_ctx->path_scope = talloc_strdup(mdscli_ctx, path_scope); + if (tevent_req_nomem(mdscli_ctx->path_scope, req)) { + return; + } + + if (mdscli_ctx->path_scope[mdscli_ctx->path_scope_len-1] == '/') { + mdscli_ctx->path_scope[mdscli_ctx->path_scope_len-1] = '\0'; + mdscli_ctx->path_scope_len--; + } + tevent_req_done(req); } @@ -276,15 +395,6 @@ return tevent_req_post(req, ev); } - state->response_blob.spotlight_blob = talloc_array( - state, - uint8_t, - mdscli_ctx->max_fragment_size); - if (tevent_req_nomem(state->response_blob.spotlight_blob, req)) { - return tevent_req_post(req, ev); - } - state->response_blob.size = mdscli_ctx->max_fragment_size; - subreq = dcerpc_mdssvc_cmd_send(state, ev, mdscli_ctx->bh, @@ -457,15 +567,6 @@ return tevent_req_post(req, ev); } - state->response_blob.spotlight_blob = talloc_array( - state, - uint8_t, - mdscli_ctx->max_fragment_size); - if (tevent_req_nomem(state->response_blob.spotlight_blob, req)) { - return tevent_req_post(req, ev); - } - state->response_blob.size = mdscli_ctx->max_fragment_size; - subreq = dcerpc_mdssvc_cmd_send(state, ev, mdscli_ctx->bh, @@ -681,15 +782,6 @@ return tevent_req_post(req, ev); } - state->response_blob.spotlight_blob = talloc_array( - state, - uint8_t, - mdscli_ctx->max_fragment_size); - if (tevent_req_nomem(state->response_blob.spotlight_blob, req)) { - return tevent_req_post(req, ev); - } - state->response_blob.size = mdscli_ctx->max_fragment_size; - subreq = dcerpc_mdssvc_cmd_send(state, ev, mdscli_ctx->bh, @@ -724,7 +816,10 @@ struct mdscli_get_path_state *state = tevent_req_data( req, struct mdscli_get_path_state); DALLOC_CTX *d = NULL; + size_t pathlen; + size_t prefixlen; char *path = NULL; + const char *p = NULL; NTSTATUS status; bool ok; @@ -759,7 +854,38 @@ tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR); return; } - state->path = talloc_move(state, &path); + + /* Path is prefixed by /PATHSCOPE/SHARENAME/, strip it */ + pathlen = strlen(path); + + /* + * path_scope_len and share_path_len are already checked to be smaller + * then UINT16_MAX so this can't overflow + */ + prefixlen = state->mdscli_ctx->path_scope_len + + state->mdscli_ctx->mdscmd_open.share_path_len; + + if (pathlen < prefixlen) { + DBG_DEBUG("Bad path: %s\n", path); + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; + } + + p = path + prefixlen; + while (*p == '/') { + p++; + } + if (*p == '\0') { + DBG_DEBUG("Bad path: %s\n", path); + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; + } + + state->path = talloc_strdup(state, p); + if (state->path == NULL) { + tevent_req_nterror(req, NT_STATUS_NO_MEMORY); + return; + } DBG_DEBUG("path: %s\n", state->path); tevent_req_done(req); @@ -852,15 +978,6 @@ return tevent_req_post(req, ev); } - state->response_blob.spotlight_blob = talloc_array( - state, - uint8_t, - mdscli_ctx->max_fragment_size); - if (tevent_req_nomem(state->response_blob.spotlight_blob, req)) { - return tevent_req_post(req, ev); - } - state->response_blob.size = mdscli_ctx->max_fragment_size; - subreq = dcerpc_mdssvc_cmd_send(state, ev, mdscli_ctx->bh, diff -Nru samba-4.17.9+dfsg/source3/rpc_client/cli_mdssvc_private.h samba-4.17.10+dfsg/source3/rpc_client/cli_mdssvc_private.h --- samba-4.17.9+dfsg/source3/rpc_client/cli_mdssvc_private.h 2022-08-08 14:15:39.436192500 +0000 +++ samba-4.17.10+dfsg/source3/rpc_client/cli_mdssvc_private.h 2023-07-14 13:15:01.033234400 +0000 @@ -42,6 +42,7 @@ /* cmd specific or unknown fields */ struct { char share_path[1025]; + size_t share_path_len; uint32_t unkn2; uint32_t unkn3; } mdscmd_open; @@ -56,6 +57,9 @@ struct { uint32_t status; } mdscmd_close; + + char *path_scope; + size_t path_scope_len; }; struct mdscli_search_ctx { diff -Nru samba-4.17.9+dfsg/source3/rpc_client/cli_mdssvc_util.c samba-4.17.10+dfsg/source3/rpc_client/cli_mdssvc_util.c --- samba-4.17.9+dfsg/source3/rpc_client/cli_mdssvc_util.c 2022-08-08 14:15:39.436192500 +0000 +++ samba-4.17.10+dfsg/source3/rpc_client/cli_mdssvc_util.c 2023-07-14 13:15:01.033234400 +0000 @@ -28,6 +28,74 @@ #include "rpc_server/mdssvc/dalloc.h" #include "rpc_server/mdssvc/marshalling.h" +NTSTATUS mdscli_blob_fetch_props(TALLOC_CTX *mem_ctx, + struct mdscli_ctx *ctx, + struct mdssvc_blob *blob) +{ + DALLOC_CTX *d = NULL; + uint64_t *uint64p = NULL; + sl_array_t *array = NULL; + sl_array_t *cmd_array = NULL; + NTSTATUS status; + int ret; + + d = dalloc_new(mem_ctx); + if (d == NULL) { + return NT_STATUS_NO_MEMORY; + } + + array = dalloc_zero(d, sl_array_t); + if (array == NULL) { + TALLOC_FREE(d); + return NT_STATUS_NO_MEMORY; + } + + ret = dalloc_add(d, array, sl_array_t); + if (ret != 0) { + TALLOC_FREE(d); + return NT_STATUS_NO_MEMORY; + } + + cmd_array = dalloc_zero(d, sl_array_t); + if (cmd_array == NULL) { + TALLOC_FREE(d); + return NT_STATUS_NO_MEMORY; + } + + ret = dalloc_add(array, cmd_array, sl_array_t); + if (ret != 0) { + TALLOC_FREE(d); + return NT_STATUS_NO_MEMORY; + } + + ret = dalloc_stradd(cmd_array, "fetchPropertiesForContext:"); + if (ret != 0) { + TALLOC_FREE(d); + return NT_STATUS_NO_MEMORY; + } + + uint64p = talloc_zero_array(cmd_array, uint64_t, 2); + if (uint64p == NULL) { + TALLOC_FREE(d); + return NT_STATUS_NO_MEMORY; + } + + talloc_set_name(uint64p, "uint64_t *"); + + ret = dalloc_add(cmd_array, uint64p, uint64_t *); + if (ret != 0) { + TALLOC_FREE(d); + return NT_STATUS_NO_MEMORY; + } + + status = sl_pack_alloc(mem_ctx, d, blob, ctx->max_fragment_size); + TALLOC_FREE(d); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + return NT_STATUS_OK; +} + NTSTATUS mdscli_blob_search(TALLOC_CTX *mem_ctx, struct mdscli_search_ctx *search, struct mdssvc_blob *blob) @@ -42,7 +110,7 @@ sl_array_t *scope_array = NULL; double dval; uint64_t uint64val; - ssize_t len; + NTSTATUS status; int ret; d = dalloc_new(mem_ctx); @@ -209,23 +277,11 @@ return NT_STATUS_NO_MEMORY; } - blob->spotlight_blob = talloc_array(d, - uint8_t, - ctx->max_fragment_size); - if (blob->spotlight_blob == NULL) { - TALLOC_FREE(d); - return NT_STATUS_NO_MEMORY; - } - blob->size = ctx->max_fragment_size; - - len = sl_pack(d, (char *)blob->spotlight_blob, blob->size); + status = sl_pack_alloc(mem_ctx, d, blob, ctx->max_fragment_size); TALLOC_FREE(d); - if (len == -1) { - return NT_STATUS_NO_MEMORY; + if (!NT_STATUS_IS_OK(status)) { + return status; } - - blob->length = len; - blob->size = len; return NT_STATUS_OK; } @@ -238,7 +294,7 @@ uint64_t *uint64p = NULL; sl_array_t *array = NULL; sl_array_t *cmd_array = NULL; - ssize_t len; + NTSTATUS status; int ret; d = dalloc_new(mem_ctx); @@ -293,23 +349,11 @@ return NT_STATUS_NO_MEMORY; } - blob->spotlight_blob = talloc_array(d, - uint8_t, - ctx->max_fragment_size); - if (blob->spotlight_blob == NULL) { - TALLOC_FREE(d); - return NT_STATUS_NO_MEMORY; - } - blob->size = ctx->max_fragment_size; - - len = sl_pack(d, (char *)blob->spotlight_blob, blob->size); + status = sl_pack_alloc(mem_ctx, d, blob, ctx->max_fragment_size); TALLOC_FREE(d); - if (len == -1) { - return NT_STATUS_NO_MEMORY; + if (!NT_STATUS_IS_OK(status)) { + return status; } - - blob->length = len; - blob->size = len; return NT_STATUS_OK; } @@ -325,7 +369,7 @@ sl_array_t *cmd_array = NULL; sl_array_t *attr_array = NULL; sl_cnids_t *cnids = NULL; - ssize_t len; + NTSTATUS status; int ret; d = dalloc_new(mem_ctx); @@ -426,23 +470,11 @@ return NT_STATUS_NO_MEMORY; } - blob->spotlight_blob = talloc_array(d, - uint8_t, - ctx->max_fragment_size); - if (blob->spotlight_blob == NULL) { - TALLOC_FREE(d); - return NT_STATUS_NO_MEMORY; - } - blob->size = ctx->max_fragment_size; - - len = sl_pack(d, (char *)blob->spotlight_blob, blob->size); + status = sl_pack_alloc(mem_ctx, d, blob, ctx->max_fragment_size); TALLOC_FREE(d); - if (len == -1) { - return NT_STATUS_NO_MEMORY; + if (!NT_STATUS_IS_OK(status)) { + return status; } - - blob->length = len; - blob->size = len; return NT_STATUS_OK; } @@ -455,7 +487,7 @@ uint64_t *uint64p = NULL; sl_array_t *array = NULL; sl_array_t *cmd_array = NULL; - ssize_t len; + NTSTATUS status; int ret; d = dalloc_new(mem_ctx); @@ -510,22 +542,10 @@ return NT_STATUS_NO_MEMORY; } - blob->spotlight_blob = talloc_array(d, - uint8_t, - ctx->max_fragment_size); - if (blob->spotlight_blob == NULL) { - TALLOC_FREE(d); - return NT_STATUS_NO_MEMORY; - } - blob->size = ctx->max_fragment_size; - - len = sl_pack(d, (char *)blob->spotlight_blob, blob->size); + status = sl_pack_alloc(mem_ctx, d, blob, ctx->max_fragment_size); TALLOC_FREE(d); - if (len == -1) { - return NT_STATUS_NO_MEMORY; + if (!NT_STATUS_IS_OK(status)) { + return status; } - - blob->length = len; - blob->size = len; return NT_STATUS_OK; } diff -Nru samba-4.17.9+dfsg/source3/rpc_client/cli_mdssvc_util.h samba-4.17.10+dfsg/source3/rpc_client/cli_mdssvc_util.h --- samba-4.17.9+dfsg/source3/rpc_client/cli_mdssvc_util.h 2022-08-08 14:15:39.436192500 +0000 +++ samba-4.17.10+dfsg/source3/rpc_client/cli_mdssvc_util.h 2023-07-14 13:15:01.033234400 +0000 @@ -21,6 +21,10 @@ #ifndef _MDSCLI_UTIL_H_ #define _MDSCLI_UTIL_H_ +NTSTATUS mdscli_blob_fetch_props(TALLOC_CTX *mem_ctx, + struct mdscli_ctx *ctx, + struct mdssvc_blob *blob); + NTSTATUS mdscli_blob_search(TALLOC_CTX *mem_ctx, struct mdscli_search_ctx *search, struct mdssvc_blob *blob); diff -Nru samba-4.17.9+dfsg/source3/rpc_server/mdssvc/dalloc.c samba-4.17.10+dfsg/source3/rpc_server/mdssvc/dalloc.c --- samba-4.17.9+dfsg/source3/rpc_server/mdssvc/dalloc.c 2022-08-08 14:15:39.440192700 +0000 +++ samba-4.17.10+dfsg/source3/rpc_server/mdssvc/dalloc.c 2023-07-14 13:14:57.597198700 +0000 @@ -159,7 +159,7 @@ int result = 0; void *p = NULL; va_list args; - const char *type; + const char *type = NULL; int elem; size_t array_len; @@ -170,7 +170,6 @@ array_len = talloc_array_length(d->dd_talloc_array); elem = va_arg(args, int); if (elem >= array_len) { - va_end(args); result = -1; goto done; } @@ -178,8 +177,6 @@ type = va_arg(args, const char *); } - va_end(args); - array_len = talloc_array_length(d->dd_talloc_array); for (elem = 0; elem + 1 < array_len; elem += 2) { @@ -192,8 +189,17 @@ break; } } + if (p == NULL) { + goto done; + } + + type = va_arg(args, const char *); + if (strcmp(talloc_get_name(p), type) != 0) { + p = NULL; + } done: + va_end(args); if (result != 0) { p = NULL; } diff -Nru samba-4.17.9+dfsg/source3/rpc_server/mdssvc/marshalling.c samba-4.17.10+dfsg/source3/rpc_server/mdssvc/marshalling.c --- samba-4.17.9+dfsg/source3/rpc_server/mdssvc/marshalling.c 2022-08-08 14:15:39.444192600 +0000 +++ samba-4.17.10+dfsg/source3/rpc_server/mdssvc/marshalling.c 2023-07-14 13:15:01.013234100 +0000 @@ -78,6 +78,7 @@ ssize_t offset, size_t bufsize, int count, ssize_t toc_offset, int encoding); +static ssize_t sl_pack(DALLOC_CTX *query, char *buf, size_t bufsize); /****************************************************************************** * Wrapper functions for the *VAL macros with bound checking @@ -1119,7 +1120,7 @@ sl_nil_t nil = 0; subcount = tag.count; - if (subcount > count) { + if (subcount < 1 || subcount > count) { return -1; } for (i = 0; i < subcount; i++) { @@ -1147,7 +1148,7 @@ case SQ_TYPE_INT64: subcount = sl_unpack_ints(query, buf, offset, bufsize, encoding); - if (subcount == -1 || subcount > count) { + if (subcount < 1 || subcount > count) { return -1; } offset += tag.size; @@ -1156,7 +1157,7 @@ case SQ_TYPE_UUID: subcount = sl_unpack_uuid(query, buf, offset, bufsize, encoding); - if (subcount == -1 || subcount > count) { + if (subcount < 1 || subcount > count) { return -1; } offset += tag.size; @@ -1165,7 +1166,7 @@ case SQ_TYPE_FLOAT: subcount = sl_unpack_floats(query, buf, offset, bufsize, encoding); - if (subcount == -1 || subcount > count) { + if (subcount < 1 || subcount > count) { return -1; } offset += tag.size; @@ -1174,7 +1175,7 @@ case SQ_TYPE_DATE: subcount = sl_unpack_date(query, buf, offset, bufsize, encoding); - if (subcount == -1 || subcount > count) { + if (subcount < 1 || subcount > count) { return -1; } offset += tag.size; @@ -1190,11 +1191,7 @@ return offset; } -/****************************************************************************** - * Global functions for packing und unpacking - ******************************************************************************/ - -ssize_t sl_pack(DALLOC_CTX *query, char *buf, size_t bufsize) +static ssize_t sl_pack(DALLOC_CTX *query, char *buf, size_t bufsize) { ssize_t result; char *toc_buf; @@ -1274,6 +1271,34 @@ return len; } +/****************************************************************************** + * Global functions for packing und unpacking + ******************************************************************************/ + +NTSTATUS sl_pack_alloc(TALLOC_CTX *mem_ctx, + DALLOC_CTX *d, + struct mdssvc_blob *b, + size_t max_fragment_size) +{ + ssize_t len; + + b->spotlight_blob = talloc_zero_array(mem_ctx, + uint8_t, + max_fragment_size); + if (b->spotlight_blob == NULL) { + return NT_STATUS_NO_MEMORY; + } + + len = sl_pack(d, (char *)b->spotlight_blob, max_fragment_size); + if (len == -1) { + return NT_STATUS_DATA_ERROR; + } + + b->length = len; + b->size = len; + return NT_STATUS_OK; +} + bool sl_unpack(DALLOC_CTX *query, const char *buf, size_t bufsize) { ssize_t result; diff -Nru samba-4.17.9+dfsg/source3/rpc_server/mdssvc/marshalling.h samba-4.17.10+dfsg/source3/rpc_server/mdssvc/marshalling.h --- samba-4.17.9+dfsg/source3/rpc_server/mdssvc/marshalling.h 2022-08-08 14:15:39.444192600 +0000 +++ samba-4.17.10+dfsg/source3/rpc_server/mdssvc/marshalling.h 2023-07-14 13:15:01.013234100 +0000 @@ -22,6 +22,9 @@ #define _MDSSVC_MARSHALLING_H #include "dalloc.h" +#include "libcli/util/ntstatus.h" +#include "lib/util/data_blob.h" +#include "librpc/gen_ndr/mdssvc.h" #define MAX_SL_FRAGMENT_SIZE 0xFFFFF @@ -49,7 +52,11 @@ * Function declarations ******************************************************************************/ -extern ssize_t sl_pack(DALLOC_CTX *query, char *buf, size_t bufsize); +extern NTSTATUS sl_pack_alloc(TALLOC_CTX *mem_ctx, + DALLOC_CTX *d, + struct mdssvc_blob *b, + size_t max_fragment_size); + extern bool sl_unpack(DALLOC_CTX *query, const char *buf, size_t bufsize); #endif diff -Nru samba-4.17.9+dfsg/source3/rpc_server/mdssvc/mdssvc.c samba-4.17.10+dfsg/source3/rpc_server/mdssvc/mdssvc.c --- samba-4.17.9+dfsg/source3/rpc_server/mdssvc/mdssvc.c 2023-03-09 09:18:38.353811000 +0000 +++ samba-4.17.10+dfsg/source3/rpc_server/mdssvc/mdssvc.c 2023-07-14 13:15:01.053234600 +0000 @@ -446,7 +446,10 @@ * entries by calling talloc_free() on the query slq handles. **/ -static bool inode_map_add(struct sl_query *slq, uint64_t ino, const char *path) +static bool inode_map_add(struct sl_query *slq, + uint64_t ino, + const char *path, + struct stat_ex *st) { NTSTATUS status; struct sl_inode_path_map *entry; @@ -493,6 +496,7 @@ entry->ino = ino; entry->mds_ctx = slq->mds_ctx; + entry->st = *st; entry->path = talloc_strdup(entry, path); if (entry->path == NULL) { DEBUG(1, ("talloc failed\n")); @@ -516,10 +520,13 @@ bool mds_add_result(struct sl_query *slq, const char *path) { struct smb_filename *smb_fname = NULL; + const char *relative = NULL; + char *fake_path = NULL; struct stat_ex sb; uint64_t ino64; int result; NTSTATUS status; + bool sub; bool ok; /* @@ -594,6 +601,17 @@ } } + sub = subdir_of(slq->mds_ctx->spath, + slq->mds_ctx->spath_len, + path, + &relative); + if (!sub) { + DBG_ERR("[%s] is not inside [%s]\n", + path, slq->mds_ctx->spath); + slq->state = SLQ_STATE_ERROR; + return false; + } + /* * Add inode number and filemeta to result set, this is what * we return as part of the result set of a query @@ -606,18 +624,30 @@ slq->state = SLQ_STATE_ERROR; return false; } + + fake_path = talloc_asprintf(slq, + "/%s/%s", + slq->mds_ctx->sharename, + relative); + if (fake_path == NULL) { + slq->state = SLQ_STATE_ERROR; + return false; + } + ok = add_filemeta(slq->mds_ctx, slq->reqinfo, slq->query_results->fm_array, - path, + fake_path, &sb); if (!ok) { DBG_ERR("add_filemeta error\n"); + TALLOC_FREE(fake_path); slq->state = SLQ_STATE_ERROR; return false; } - ok = inode_map_add(slq, ino64, path); + ok = inode_map_add(slq, ino64, fake_path, &sb); + TALLOC_FREE(fake_path); if (!ok) { DEBUG(1, ("inode_map_add error\n")); slq->state = SLQ_STATE_ERROR; @@ -726,6 +756,10 @@ } /* kMDSStoreMetaScopes array */ + result = dalloc_stradd(dict, "kMDSStoreMetaScopes"); + if (result != 0) { + return false; + } array = dalloc_zero(dict, sl_array_t); if (array == NULL) { return NULL; @@ -821,6 +855,32 @@ } /** + * Translate a fake scope from the client like /sharename/dir + * to the real server-side path, replacing the "/sharename" part + * with the absolute server-side path of the share. + **/ +static bool mdssvc_real_scope(struct sl_query *slq, const char *fake_scope) +{ + size_t sname_len = strlen(slq->mds_ctx->sharename); + size_t fake_scope_len = strlen(fake_scope); + + if (fake_scope_len < sname_len + 1) { + DBG_ERR("Short scope [%s] for share [%s]\n", + fake_scope, slq->mds_ctx->sharename); + return false; + } + + slq->path_scope = talloc_asprintf(slq, + "%s%s", + slq->mds_ctx->spath, + fake_scope + sname_len + 1); + if (slq->path_scope == NULL) { + return false; + } + return true; +} + +/** * Begin a search query **/ static bool slrpc_open_query(struct mds_ctx *mds_ctx, @@ -872,7 +932,8 @@ querystring = dalloc_value_for_key(query, "DALLOC_CTX", 0, "DALLOC_CTX", 1, - "kMDQueryString"); + "kMDQueryString", + "char *"); if (querystring == NULL) { DEBUG(1, ("missing kMDQueryString\n")); goto error; @@ -912,8 +973,11 @@ slq->ctx2 = *uint64p; path_scope = dalloc_value_for_key(query, "DALLOC_CTX", 0, - "DALLOC_CTX", 1, "kMDScopeArray"); + "DALLOC_CTX", 1, + "kMDScopeArray", + "sl_array_t"); if (path_scope == NULL) { + DBG_ERR("missing kMDScopeArray\n"); goto error; } @@ -928,14 +992,17 @@ goto error; } - slq->path_scope = talloc_strdup(slq, scope); - if (slq->path_scope == NULL) { + ok = mdssvc_real_scope(slq, scope); + if (!ok) { goto error; } reqinfo = dalloc_value_for_key(query, "DALLOC_CTX", 0, - "DALLOC_CTX", 1, "kMDAttributeArray"); + "DALLOC_CTX", 1, + "kMDAttributeArray", + "sl_array_t"); if (reqinfo == NULL) { + DBG_ERR("missing kMDAttributeArray\n"); goto error; } @@ -943,7 +1010,9 @@ DEBUG(10, ("requested attributes: %s", dalloc_dump(reqinfo, 0))); cnids = dalloc_value_for_key(query, "DALLOC_CTX", 0, - "DALLOC_CTX", 1, "kMDQueryItemArray"); + "DALLOC_CTX", 1, + "kMDQueryItemArray", + "sl_array_t"); if (cnids) { ok = sort_cnids(slq, cnids->ca_cnids); if (!ok) { @@ -1331,29 +1400,7 @@ elem = talloc_get_type_abort(p, struct sl_inode_path_map); path = elem->path; - status = synthetic_pathref(talloc_tos(), - mds_ctx->conn->cwd_fsp, - path, - NULL, - NULL, - 0, - 0, - &smb_fname); - if (!NT_STATUS_IS_OK(status)) { - /* This is not an error, the user may lack permissions */ - DBG_DEBUG("synthetic_pathref [%s]: %s\n", - smb_fname_str_dbg(smb_fname), - nt_errstr(status)); - return true; - } - - status = vfs_stat_fsp(smb_fname->fsp); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(smb_fname); - return true; - } - - sp = &smb_fname->fsp->fsp_name->st; + sp = &elem->st; } ok = add_filemeta(mds_ctx, reqinfo, fm_array, path, sp); @@ -1667,6 +1714,7 @@ status = NT_STATUS_NO_MEMORY; goto error; } + mds_ctx->spath_len = strlen(path); mds_ctx->snum = snum; mds_ctx->pipe_session_info = session_info; @@ -1737,11 +1785,11 @@ **/ bool mds_dispatch(struct mds_ctx *mds_ctx, struct mdssvc_blob *request_blob, - struct mdssvc_blob *response_blob) + struct mdssvc_blob *response_blob, + size_t max_fragment_size) { bool ok; int ret; - ssize_t len; DALLOC_CTX *query = NULL; DALLOC_CTX *reply = NULL; char *rpccmd; @@ -1749,6 +1797,7 @@ const struct smb_filename conn_basedir = { .base_name = mds_ctx->conn->connectpath, }; + NTSTATUS status; if (CHECK_DEBUGLVL(10)) { const struct sl_query *slq; @@ -1809,18 +1858,19 @@ } ok = slcmd->function(mds_ctx, query, reply); - if (ok) { - DBG_DEBUG("%s", dalloc_dump(reply, 0)); + if (!ok) { + goto cleanup; + } - len = sl_pack(reply, - (char *)response_blob->spotlight_blob, - response_blob->size); - if (len == -1) { - DBG_ERR("error packing Spotlight RPC reply\n"); - ok = false; - goto cleanup; - } - response_blob->length = len; + DBG_DEBUG("%s", dalloc_dump(reply, 0)); + + status = sl_pack_alloc(response_blob, + reply, + response_blob, + max_fragment_size); + if (!NT_STATUS_IS_OK(status)) { + DBG_ERR("sl_pack_alloc() failed\n"); + goto cleanup; } cleanup: diff -Nru samba-4.17.9+dfsg/source3/rpc_server/mdssvc/mdssvc.h samba-4.17.10+dfsg/source3/rpc_server/mdssvc/mdssvc.h --- samba-4.17.9+dfsg/source3/rpc_server/mdssvc/mdssvc.h 2022-08-08 14:15:39.444192600 +0000 +++ samba-4.17.10+dfsg/source3/rpc_server/mdssvc/mdssvc.h 2023-07-14 13:15:01.053234600 +0000 @@ -105,6 +105,7 @@ struct mds_ctx *mds_ctx; uint64_t ino; char *path; + struct stat_ex st; }; /* Per process state */ @@ -126,6 +127,7 @@ int snum; const char *sharename; const char *spath; + size_t spath_len; struct connection_struct *conn; struct sl_query *query_list; /* list of active queries */ struct db_context *ino_path_map; /* dbwrap rbt for storing inode->path mappings */ @@ -157,9 +159,10 @@ const char *sharename, const char *path, struct mds_ctx **_mds_ctx); -extern bool mds_dispatch(struct mds_ctx *query_ctx, +extern bool mds_dispatch(struct mds_ctx *mds_ctx, struct mdssvc_blob *request_blob, - struct mdssvc_blob *response_blob); + struct mdssvc_blob *response_blob, + size_t max_fragment_size); bool mds_add_result(struct sl_query *slq, const char *path); #endif /* _MDSSVC_H */ diff -Nru samba-4.17.9+dfsg/source3/rpc_server/mdssvc/srv_mdssvc_nt.c samba-4.17.10+dfsg/source3/rpc_server/mdssvc/srv_mdssvc_nt.c --- samba-4.17.9+dfsg/source3/rpc_server/mdssvc/srv_mdssvc_nt.c 2022-08-08 14:15:39.444192600 +0000 +++ samba-4.17.10+dfsg/source3/rpc_server/mdssvc/srv_mdssvc_nt.c 2023-07-14 13:15:01.053234600 +0000 @@ -81,6 +81,7 @@ loadparm_s3_global_substitution(); int snum; char *outpath = discard_const_p(char, r->out.share_path); + char *fake_path = NULL; char *path; NTSTATUS status; @@ -98,12 +99,21 @@ path = lp_path(talloc_tos(), lp_sub, snum); if (path == NULL) { - DBG_ERR("Couldn't create policy handle for %s\n", + DBG_ERR("Couldn't create path for %s\n", r->in.share_name); p->fault_state = DCERPC_FAULT_CANT_PERFORM; return; } + fake_path = talloc_asprintf(p->mem_ctx, "/%s", r->in.share_name); + if (fake_path == NULL) { + DBG_ERR("Couldn't create fake share path for %s\n", + r->in.share_name); + talloc_free(path); + p->fault_state = DCERPC_FAULT_CANT_PERFORM; + return; + } + status = create_mdssvc_policy_handle(p->mem_ctx, p, snum, r->in.share_name, @@ -112,18 +122,20 @@ if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_VOLUME)) { ZERO_STRUCTP(r->out.handle); talloc_free(path); + talloc_free(fake_path); return; } if (!NT_STATUS_IS_OK(status)) { DBG_ERR("Couldn't create policy handle for %s\n", r->in.share_name); talloc_free(path); + talloc_free(fake_path); p->fault_state = DCERPC_FAULT_CANT_PERFORM; return; } - strlcpy(outpath, path, 1024); - talloc_free(path); + strlcpy(outpath, fake_path, 1024); + talloc_free(fake_path); return; } @@ -164,7 +176,6 @@ struct auth_session_info *session_info = dcesrv_call_session_info(dce_call); bool ok; - char *rbuf; struct mds_ctx *mds_ctx; NTSTATUS status; @@ -221,18 +232,13 @@ return; } - rbuf = talloc_zero_array(p->mem_ctx, char, r->in.max_fragment_size1); - if (rbuf == NULL) { - p->fault_state = DCERPC_FAULT_CANT_PERFORM; - return; - } - r->out.response_blob->spotlight_blob = (uint8_t *)rbuf; - r->out.response_blob->size = r->in.max_fragment_size1; - /* We currently don't use fragmentation at the mdssvc RPC layer */ *r->out.fragment = 0; - ok = mds_dispatch(mds_ctx, &r->in.request_blob, r->out.response_blob); + ok = mds_dispatch(mds_ctx, + &r->in.request_blob, + r->out.response_blob, + r->in.max_fragment_size1); if (ok) { *r->out.unkn9 = 0; } else { diff -Nru samba-4.17.9+dfsg/source3/rpc_server/netlogon/srv_netlog_nt.c samba-4.17.10+dfsg/source3/rpc_server/netlogon/srv_netlog_nt.c --- samba-4.17.9+dfsg/source3/rpc_server/netlogon/srv_netlog_nt.c 2023-01-26 17:45:01.653668600 +0000 +++ samba-4.17.10+dfsg/source3/rpc_server/netlogon/srv_netlog_nt.c 2023-07-17 08:28:30.170744400 +0000 @@ -2286,6 +2286,31 @@ struct netlogon_creds_CredentialState *creds; NTSTATUS status; + switch (r->in.query_level) { + case 1: + break; + case 2: + /* + * Until we know the details behind KB5028166 + * just return DCERPC_NCA_S_FAULT_INVALID_TAG + * like an unpatched Windows Server. + */ + FALL_THROUGH; + default: + /* + * There would not be a way to marshall the + * the response. Which would mean our final + * ndr_push would fail an we would return + * an RPC-level fault with DCERPC_FAULT_BAD_STUB_DATA. + * + * But it's important to match a Windows server + * especially before KB5028166, see also our bug #15418 + * Otherwise Windows client would stop talking to us. + */ + p->fault_state = DCERPC_NCA_S_FAULT_INVALID_TAG; + return NT_STATUS_NOT_SUPPORTED; + } + become_root(); status = dcesrv_netr_creds_server_step_check(p->dce_call, p->mem_ctx, @@ -2298,10 +2323,6 @@ return status; } - if (r->in.query_level != 1) { - return NT_STATUS_NOT_SUPPORTED; - } - r->out.capabilities->server_capabilities = creds->negotiate_flags; return NT_STATUS_OK; diff -Nru samba-4.17.9+dfsg/source3/rpcclient/cmd_spotlight.c samba-4.17.10+dfsg/source3/rpcclient/cmd_spotlight.c --- samba-4.17.9+dfsg/source3/rpcclient/cmd_spotlight.c 2022-08-08 14:15:39.456192700 +0000 +++ samba-4.17.10+dfsg/source3/rpcclient/cmd_spotlight.c 2023-07-14 13:15:01.013234100 +0000 @@ -43,7 +43,6 @@ uint32_t unkn3; /* server always returns 0 ? */ struct mdssvc_blob request_blob; struct mdssvc_blob response_blob; - ssize_t len; uint32_t max_fragment_size = 64 * 1024; DALLOC_CTX *d, *mds_reply; uint64_t *uint64var; @@ -137,27 +136,10 @@ goto done; } - request_blob.spotlight_blob = talloc_array(mem_ctx, uint8_t, max_fragment_size); - if (request_blob.spotlight_blob == NULL) { - status = NT_STATUS_INTERNAL_ERROR; - goto done; - } - request_blob.size = max_fragment_size; - - response_blob.spotlight_blob = talloc_array(mem_ctx, uint8_t, max_fragment_size); - if (response_blob.spotlight_blob == NULL) { - status = NT_STATUS_INTERNAL_ERROR; - goto done; - } - response_blob.size = max_fragment_size; - - len = sl_pack(d, (char *)request_blob.spotlight_blob, request_blob.size); - if (len == -1) { - status = NT_STATUS_INTERNAL_ERROR; + status = sl_pack_alloc(mem_ctx, d, &request_blob, max_fragment_size); + if (!NT_STATUS_IS_OK(status)) { goto done; } - request_blob.length = len; - request_blob.size = len; status = dcerpc_mdssvc_cmd(b, mem_ctx, &share_handle, @@ -211,7 +193,6 @@ uint32_t unkn3; /* server always returns 0 ? */ struct mdssvc_blob request_blob; struct mdssvc_blob response_blob; - ssize_t len; uint32_t max_fragment_size = 64 * 1024; DALLOC_CTX *d, *mds_reply; uint64_t *uint64var; @@ -359,31 +340,10 @@ goto done; } - request_blob.spotlight_blob = talloc_array(mem_ctx, - uint8_t, - max_fragment_size); - if (request_blob.spotlight_blob == NULL) { - status = NT_STATUS_INTERNAL_ERROR; - goto done; - } - request_blob.size = max_fragment_size; - - response_blob.spotlight_blob = talloc_array(mem_ctx, - uint8_t, - max_fragment_size); - if (response_blob.spotlight_blob == NULL) { - status = NT_STATUS_INTERNAL_ERROR; - goto done; - } - response_blob.size = max_fragment_size; - - len = sl_pack(d, (char *)request_blob.spotlight_blob, request_blob.size); - if (len == -1) { - status = NT_STATUS_INTERNAL_ERROR; + status = sl_pack_alloc(mem_ctx, d, &request_blob, max_fragment_size); + if (!NT_STATUS_IS_OK(status)) { goto done; } - request_blob.length = len; - request_blob.size = len; status = dcerpc_mdssvc_cmd(b, mem_ctx, &share_handle, diff -Nru samba-4.17.9+dfsg/source3/selftest/tests.py samba-4.17.10+dfsg/source3/selftest/tests.py --- samba-4.17.9+dfsg/source3/selftest/tests.py 2023-07-06 13:42:43.024796700 +0000 +++ samba-4.17.10+dfsg/source3/selftest/tests.py 2023-07-14 13:15:04.453269700 +0000 @@ -938,6 +938,8 @@ # Certain tests fail when run against ad_member with MIT kerberos because the private krb5.conf overrides the provisioned lib/krb5.conf, # ad_member_idmap_rid sets "create krb5.conf = no" plansmbtorture4testsuite(t, "ad_member_idmap_rid", '//$SERVER/tmp -k yes -U$DC_USERNAME@$REALM%$DC_PASSWORD', 'krb5') + elif t == "smb2.session-require-signing": + plansmbtorture4testsuite(t, "ad_member_idmap_rid", '//$SERVER_IP/tmp -U$DC_USERNAME@$REALM%$DC_PASSWORD') elif t == "rpc.lsa": plansmbtorture4testsuite(t, "nt4_dc", '//$SERVER_IP/tmp -U$USERNAME%$PASSWORD', 'over ncacn_np ') plansmbtorture4testsuite(t, "nt4_dc", 'ncacn_ip_tcp:$SERVER_IP -U$USERNAME%$PASSWORD', 'over ncacn_ip_tcp ') diff -Nru samba-4.17.9+dfsg/source3/smbd/proto.h samba-4.17.10+dfsg/source3/smbd/proto.h --- samba-4.17.9+dfsg/source3/smbd/proto.h 2022-08-23 14:45:49.528087900 +0000 +++ samba-4.17.10+dfsg/source3/smbd/proto.h 2023-07-14 13:15:04.569270800 +0000 @@ -52,7 +52,6 @@ /* The following definitions come from smbd/smb2_signing.c */ -bool smb2_srv_init_signing(struct smbXsrv_connection *conn); bool srv_init_signing(struct smbXsrv_connection *conn); /* The following definitions come from smbd/aio.c */ diff -Nru samba-4.17.9+dfsg/source3/smbd/smb1_signing.c samba-4.17.10+dfsg/source3/smbd/smb1_signing.c --- samba-4.17.9+dfsg/source3/smbd/smb1_signing.c 2022-08-08 14:15:39.484192800 +0000 +++ samba-4.17.10+dfsg/source3/smbd/smb1_signing.c 2023-07-14 13:15:04.541270500 +0000 @@ -170,18 +170,13 @@ Called by server negprot when signing has been negotiated. ************************************************************/ -bool smb1_srv_init_signing(struct smbXsrv_connection *conn) +bool smb1_srv_init_signing(struct loadparm_context *lp_ctx, + struct smbXsrv_connection *conn) { bool allowed = true; bool desired; bool mandatory = false; - struct loadparm_context *lp_ctx = loadparm_init_s3(conn, loadparm_s3_helpers()); - if (lp_ctx == NULL) { - DEBUG(10, ("loadparm_init_s3 failed\n")); - return false; - } - /* * if the client and server allow signing, * we desire to use it. @@ -195,7 +190,6 @@ */ desired = lpcfg_server_signing_allowed(lp_ctx, &mandatory); - talloc_unlink(conn, lp_ctx); if (lp_async_smb_echo_handler()) { struct smbd_shm_signing *s; diff -Nru samba-4.17.9+dfsg/source3/smbd/smb1_signing.h samba-4.17.10+dfsg/source3/smbd/smb1_signing.h --- samba-4.17.9+dfsg/source3/smbd/smb1_signing.h 2022-08-08 14:15:39.484192800 +0000 +++ samba-4.17.10+dfsg/source3/smbd/smb1_signing.h 2023-07-14 13:15:04.541270500 +0000 @@ -33,4 +33,5 @@ void smb1_srv_set_signing(struct smbXsrv_connection *conn, const DATA_BLOB user_session_key, const DATA_BLOB response); -bool smb1_srv_init_signing(struct smbXsrv_connection *conn); +bool smb1_srv_init_signing(struct loadparm_context *lp_ctx, + struct smbXsrv_connection *conn); diff -Nru samba-4.17.9+dfsg/source3/smbd/smb2_negprot.c samba-4.17.10+dfsg/source3/smbd/smb2_negprot.c --- samba-4.17.9+dfsg/source3/smbd/smb2_negprot.c 2022-08-08 14:29:11.369506800 +0000 +++ samba-4.17.10+dfsg/source3/smbd/smb2_negprot.c 2023-07-14 13:15:04.589271000 +0000 @@ -361,12 +361,6 @@ } security_mode = SMB2_NEGOTIATE_SIGNING_ENABLED; - /* - * We use xconn->smb2.signing_mandatory set up via - * srv_init_signing() -> smb2_srv_init_signing(). - * This calls lpcfg_server_signing_allowed() to get the correct - * defaults, e.g. signing_required for an ad_dc. - */ if (xconn->smb2.signing_mandatory) { security_mode |= SMB2_NEGOTIATE_SIGNING_REQUIRED; } diff -Nru samba-4.17.9+dfsg/source3/smbd/smb2_signing.c samba-4.17.10+dfsg/source3/smbd/smb2_signing.c --- samba-4.17.9+dfsg/source3/smbd/smb2_signing.c 2022-08-08 14:15:39.492193000 +0000 +++ samba-4.17.10+dfsg/source3/smbd/smb2_signing.c 2023-07-14 13:15:04.609271300 +0000 @@ -26,9 +26,12 @@ #include "lib/param/param.h" #include "smb2_signing.h" -bool smb2_srv_init_signing(struct smbXsrv_connection *conn) +bool srv_init_signing(struct smbXsrv_connection *conn) { - struct loadparm_context *lp_ctx = loadparm_init_s3(conn, loadparm_s3_helpers()); + struct loadparm_context *lp_ctx = NULL; + bool ok = true; + + lp_ctx = loadparm_init_s3(conn, loadparm_s3_helpers()); if (lp_ctx == NULL) { DBG_DEBUG("loadparm_init_s3 failed\n"); return false; @@ -39,19 +42,11 @@ * It is always allowed and desired, whatever the smb.conf says. */ (void)lpcfg_server_signing_allowed(lp_ctx, &conn->smb2.signing_mandatory); - talloc_unlink(conn, lp_ctx); - return true; -} -bool srv_init_signing(struct smbXsrv_connection *conn) -{ #if defined(WITH_SMB1SERVER) - if (conn->protocol >= PROTOCOL_SMB2_02) { -#endif - return smb2_srv_init_signing(conn); -#if defined(WITH_SMB1SERVER) - } else { - return smb1_srv_init_signing(conn); - } + ok = smb1_srv_init_signing(lp_ctx, conn); #endif + + talloc_unlink(conn, lp_ctx); + return ok; } diff -Nru samba-4.17.9+dfsg/source3/utils/ntlm_auth.c samba-4.17.10+dfsg/source3/utils/ntlm_auth.c --- samba-4.17.9+dfsg/source3/utils/ntlm_auth.c 2022-12-15 16:09:31.745236600 +0000 +++ samba-4.17.10+dfsg/source3/utils/ntlm_auth.c 2023-07-14 13:14:46.665085300 +0000 @@ -576,10 +576,14 @@ memcpy(request.data.auth_crap.chal, challenge->data, MIN(challenge->length, 8)); if (lm_response && lm_response->length) { + size_t capped_lm_response_len = MIN( + lm_response->length, + sizeof(request.data.auth_crap.lm_resp)); + memcpy(request.data.auth_crap.lm_resp, lm_response->data, - MIN(lm_response->length, sizeof(request.data.auth_crap.lm_resp))); - request.data.auth_crap.lm_resp_len = lm_response->length; + capped_lm_response_len); + request.data.auth_crap.lm_resp_len = capped_lm_response_len; } if (nt_response && nt_response->length) { diff -Nru samba-4.17.9+dfsg/source3/winbindd/winbindd_pam_auth_crap.c samba-4.17.10+dfsg/source3/winbindd/winbindd_pam_auth_crap.c --- samba-4.17.9+dfsg/source3/winbindd/winbindd_pam_auth_crap.c 2022-08-08 14:15:39.528193200 +0000 +++ samba-4.17.10+dfsg/source3/winbindd/winbindd_pam_auth_crap.c 2023-07-14 13:14:46.637085200 +0000 @@ -52,6 +52,9 @@ DATA_BLOB chal = data_blob_null; struct wbint_SidArray *require_membership_of_sid = NULL; NTSTATUS status; + bool lmlength_ok = false; + bool ntlength_ok = false; + bool pwlength_ok = false; req = tevent_req_create(mem_ctx, &state, struct winbindd_pam_auth_crap_state); @@ -115,16 +118,24 @@ fstrcpy(request->data.auth_crap.workstation, lp_netbios_name()); } - if (request->data.auth_crap.lm_resp_len > sizeof(request->data.auth_crap.lm_resp) - || request->data.auth_crap.nt_resp_len > sizeof(request->data.auth_crap.nt_resp)) { - if (!(request->flags & WBFLAG_BIG_NTLMV2_BLOB) || - request->extra_len != request->data.auth_crap.nt_resp_len) { - DBG_ERR("Invalid password length %u/%u\n", - request->data.auth_crap.lm_resp_len, - request->data.auth_crap.nt_resp_len); - tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); - return tevent_req_post(req, ev); - } + lmlength_ok = (request->data.auth_crap.lm_resp_len <= + sizeof(request->data.auth_crap.lm_resp)); + + ntlength_ok = (request->data.auth_crap.nt_resp_len <= + sizeof(request->data.auth_crap.nt_resp)); + + ntlength_ok |= + ((request->flags & WBFLAG_BIG_NTLMV2_BLOB) && + (request->extra_len == request->data.auth_crap.nt_resp_len)); + + pwlength_ok = lmlength_ok && ntlength_ok; + + if (!pwlength_ok) { + DBG_ERR("Invalid password length %u/%u\n", + request->data.auth_crap.lm_resp_len, + request->data.auth_crap.nt_resp_len); + tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); + return tevent_req_post(req, ev); } state->domain = talloc_strdup(state, request->data.auth_crap.domain); diff -Nru samba-4.17.9+dfsg/source4/rpc_server/netlogon/dcerpc_netlogon.c samba-4.17.10+dfsg/source4/rpc_server/netlogon/dcerpc_netlogon.c --- samba-4.17.9+dfsg/source4/rpc_server/netlogon/dcerpc_netlogon.c 2023-01-26 17:45:01.661668500 +0000 +++ samba-4.17.10+dfsg/source4/rpc_server/netlogon/dcerpc_netlogon.c 2023-07-17 08:28:30.146744000 +0000 @@ -2359,6 +2359,30 @@ struct netlogon_creds_CredentialState *creds; NTSTATUS status; + switch (r->in.query_level) { + case 1: + break; + case 2: + /* + * Until we know the details behind KB5028166 + * just return DCERPC_NCA_S_FAULT_INVALID_TAG + * like an unpatched Windows Server. + */ + FALL_THROUGH; + default: + /* + * There would not be a way to marshall the + * the response. Which would mean our final + * ndr_push would fail an we would return + * an RPC-level fault with DCERPC_FAULT_BAD_STUB_DATA. + * + * But it's important to match a Windows server + * especially before KB5028166, see also our bug #15418 + * Otherwise Windows client would stop talking to us. + */ + DCESRV_FAULT(DCERPC_NCA_S_FAULT_INVALID_TAG); + } + status = dcesrv_netr_creds_server_step_check(dce_call, mem_ctx, r->in.computer_name, @@ -2370,10 +2394,6 @@ } NT_STATUS_NOT_OK_RETURN(status); - if (r->in.query_level != 1) { - return NT_STATUS_NOT_SUPPORTED; - } - r->out.capabilities->server_capabilities = creds->negotiate_flags; return NT_STATUS_OK; diff -Nru samba-4.17.9+dfsg/source4/torture/rpc/mdssvc.c samba-4.17.10+dfsg/source4/torture/rpc/mdssvc.c --- samba-4.17.9+dfsg/source4/torture/rpc/mdssvc.c 2022-08-08 14:15:40.472200400 +0000 +++ samba-4.17.10+dfsg/source4/torture/rpc/mdssvc.c 2023-07-14 13:15:01.013234100 +0000 @@ -536,13 +536,6 @@ request_blob.length = 0; request_blob.size = 0; - response_blob.spotlight_blob = talloc_array(state, - uint8_t, - 0); - torture_assert_not_null_goto(tctx, response_blob.spotlight_blob, - ok, done, "dalloc_zero failed\n"); - response_blob.size = 0; - status = dcerpc_mdssvc_cmd(b, state, &ph, @@ -569,6 +562,218 @@ return ok; } +static uint8_t test_sl_unpack_loop_buf[] = { + 0x34, 0x33, 0x32, 0x31, 0x33, 0x30, 0x64, 0x6d, + 0x1d, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x07, 0x04, 0x00, 0x00, 0x00, + 0x66, 0x65, 0x74, 0x63, 0x68, 0x41, 0x74, 0x74, + 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x3a, + 0x66, 0x6f, 0x72, 0x4f, 0x49, 0x44, 0x41, 0x72, + 0x72, 0x61, 0x79, 0x3a, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x78, 0x74, 0x3a, 0x00, 0x00, 0x00, 0xea, + 0x02, 0x00, 0x00, 0x84, 0x02, 0x00, 0x00, 0x00, + 0x0a, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x07, 0x03, 0x00, 0x00, 0x00, + 0x6b, 0x4d, 0x44, 0x49, 0x74, 0x65, 0x6d, 0x50, + 0x61, 0x74, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x02, 0x06, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x87, 0x08, 0x00, 0x00, 0x00, + 0x01, 0x00, 0xdd, 0x0a, 0x20, 0x00, 0x00, 0x6b, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x0a, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x0a, 0x03, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x0c, 0x04, 0x00, 0x00, 0x00, + 0x0e, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x00, + 0x0f, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x00, + 0x13, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; + +static bool test_mdssvc_sl_unpack_loop(struct torture_context *tctx, + void *data) +{ + struct torture_mdsscv_state *state = talloc_get_type_abort( + data, struct torture_mdsscv_state); + struct dcerpc_binding_handle *b = state->p->binding_handle; + struct mdssvc_blob request_blob; + struct mdssvc_blob response_blob; + uint32_t device_id; + uint32_t unkn2; + uint32_t unkn9; + uint32_t fragment; + uint32_t flags; + NTSTATUS status; + bool ok = true; + + device_id = UINT32_C(0x2f000045); + unkn2 = 23; + unkn9 = 0; + fragment = 0; + flags = UINT32_C(0x6b000001); + + request_blob.spotlight_blob = test_sl_unpack_loop_buf; + request_blob.size = sizeof(test_sl_unpack_loop_buf); + request_blob.length = sizeof(test_sl_unpack_loop_buf); + + status = dcerpc_mdssvc_cmd(b, + state, + &state->ph, + 0, + device_id, + unkn2, + 0, + flags, + request_blob, + 0, + 64 * 1024, + 1, + 64 * 1024, + 0, + 0, + &fragment, + &response_blob, + &unkn9); + torture_assert_ntstatus_ok_goto( + tctx, status, ok, done, + "dcerpc_mdssvc_unknown1 failed\n"); + +done: + return ok; +} + +static bool test_sl_dict_type_safety(struct torture_context *tctx, + void *data) +{ + struct torture_mdsscv_state *state = talloc_get_type_abort( + data, struct torture_mdsscv_state); + struct dcerpc_binding_handle *b = state->p->binding_handle; + struct mdssvc_blob request_blob; + struct mdssvc_blob response_blob; + uint64_t ctx1 = 0xdeadbeef; + uint64_t ctx2 = 0xcafebabe; + uint32_t device_id; + uint32_t unkn2; + uint32_t unkn9; + uint32_t fragment; + uint32_t flags; + DALLOC_CTX *d = NULL; + sl_array_t *array1 = NULL, *array2 = NULL; + sl_dict_t *arg = NULL; + int result; + NTSTATUS status; + bool ok = true; + + device_id = UINT32_C(0x2f000045); + unkn2 = 23; + unkn9 = 0; + fragment = 0; + flags = UINT32_C(0x6b000001); + + d = dalloc_new(tctx); + torture_assert_not_null_goto(tctx, d, + ok, done, "dalloc_new failed\n"); + + array1 = dalloc_zero(d, sl_array_t); + torture_assert_not_null_goto(tctx, array1, + ok, done, "dalloc_zero failed\n"); + + array2 = dalloc_zero(d, sl_array_t); + torture_assert_not_null_goto(tctx, array2, + ok, done, "dalloc_new failed\n"); + + result = dalloc_stradd(array2, "openQueryWithParams:forContext:"); + torture_assert_goto(tctx, result == 0, + ok, done, "dalloc_stradd failed\n"); + + result = dalloc_add_copy(array2, &ctx1, uint64_t); + torture_assert_goto(tctx, result == 0, + ok, done, "dalloc_stradd failed\n"); + + result = dalloc_add_copy(array2, &ctx2, uint64_t); + torture_assert_goto(tctx, result == 0, + ok, done, "dalloc_stradd failed\n"); + + arg = dalloc_zero(array1, sl_dict_t); + torture_assert_not_null_goto(tctx, d, + ok, done, "dalloc_zero failed\n"); + + result = dalloc_stradd(arg, "kMDQueryString"); + torture_assert_goto(tctx, result == 0, + ok, done, "dalloc_stradd failed\n"); + + result = dalloc_stradd(arg, "*"); + torture_assert_goto(tctx, result == 0, + ok, done, "dalloc_stradd failed\n"); + + result = dalloc_stradd(arg, "kMDScopeArray"); + torture_assert_goto(tctx, result == 0, + ok, done, "dalloc_stradd failed\n"); + + result = dalloc_stradd(arg, "AAAABBBB"); + torture_assert_goto(tctx, result == 0, + ok, done, "dalloc_stradd failed\n"); + + result = dalloc_add(array1, array2, sl_array_t); + torture_assert_goto(tctx, result == 0, + ok, done, "dalloc_add failed\n"); + + result = dalloc_add(array1, arg, sl_dict_t); + torture_assert_goto(tctx, result == 0, + ok, done, "dalloc_add failed\n"); + + result = dalloc_add(d, array1, sl_array_t); + torture_assert_goto(tctx, result == 0, + ok, done, "dalloc_add failed\n"); + + torture_comment(tctx, "%s", dalloc_dump(d, 0)); + + request_blob.spotlight_blob = talloc_array(tctx, + uint8_t, + 64 * 1024); + torture_assert_not_null_goto(tctx, request_blob.spotlight_blob, + ok, done, "dalloc_new failed\n"); + request_blob.size = 64 * 1024; + + status = sl_pack_alloc(tctx, d, &request_blob, 64 * 1024); + torture_assert_ntstatus_ok_goto(tctx, status, ok, done, + "sl_pack_alloc() failed\n"); + + status = dcerpc_mdssvc_cmd(b, + state, + &state->ph, + 0, + device_id, + unkn2, + 0, + flags, + request_blob, + 0, + 64 * 1024, + 1, + 64 * 1024, + 0, + 0, + &fragment, + &response_blob, + &unkn9); + torture_assert_ntstatus_ok_goto( + tctx, status, ok, done, + "dcerpc_mdssvc_cmd failed\n"); + +done: + return ok; +} + static bool test_mdssvc_invalid_ph_close(struct torture_context *tctx, void *data) { @@ -628,7 +833,6 @@ const char *path_type = NULL; uint64_t ino64; NTSTATUS status; - ssize_t len; int ret; bool ok = true; @@ -693,25 +897,9 @@ ret = dalloc_add(array, cnids, sl_cnids_t); torture_assert_goto(tctx, ret == 0, ret, done, "dalloc_add failed\n"); - request_blob.spotlight_blob = talloc_array(state, - uint8_t, - max_fragment_size); - torture_assert_not_null_goto(tctx, request_blob.spotlight_blob, - ret, done, "dalloc_zero failed\n"); - request_blob.size = max_fragment_size; - - response_blob.spotlight_blob = talloc_array(state, - uint8_t, - max_fragment_size); - torture_assert_not_null_goto(tctx, response_blob.spotlight_blob, - ret, done, "dalloc_zero failed\n"); - response_blob.size = max_fragment_size; - - len = sl_pack(d, (char *)request_blob.spotlight_blob, request_blob.size); - torture_assert_goto(tctx, len != -1, ret, done, "sl_pack failed\n"); - - request_blob.length = len; - request_blob.size = len; + status = sl_pack_alloc(tctx, d, &request_blob, max_fragment_size); + torture_assert_ntstatus_ok_goto(tctx, status, ok, done, + "sl_pack_alloc() failed\n"); status = dcerpc_mdssvc_cmd(b, state, @@ -840,5 +1028,13 @@ "fetch_unknown_cnid", test_mdssvc_fetch_attr_unknown_cnid); + torture_tcase_add_simple_test(tcase, + "mdssvc_sl_unpack_loop", + test_mdssvc_sl_unpack_loop); + + torture_tcase_add_simple_test(tcase, + "sl_dict_type_safety", + test_sl_dict_type_safety); + return suite; } diff -Nru samba-4.17.9+dfsg/source4/torture/rpc/netlogon.c samba-4.17.10+dfsg/source4/torture/rpc/netlogon.c --- samba-4.17.9+dfsg/source4/torture/rpc/netlogon.c 2022-12-15 16:09:31.757236700 +0000 +++ samba-4.17.10+dfsg/source4/torture/rpc/netlogon.c 2023-07-17 08:28:30.114743500 +0000 @@ -2056,8 +2056,47 @@ r.out.capabilities = &capabilities; r.out.return_authenticator = &return_auth; - torture_comment(tctx, "Testing LogonGetCapabilities\n"); + torture_comment(tctx, "Testing LogonGetCapabilities with query_level=0\n"); + r.in.query_level = 0; + ZERO_STRUCT(return_auth); + + /* + * we need to operate on a temporary copy of creds + * because dcerpc_netr_LogonGetCapabilities with + * an unknown query level returns DCERPC_NCA_S_FAULT_INVALID_TAG + * => NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE + * without looking a the authenticator. + */ + tmp_creds = *creds; + netlogon_creds_client_authenticator(&tmp_creds, &auth); + + status = dcerpc_netr_LogonGetCapabilities_r(b, tctx, &r); + torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE, + "LogonGetCapabilities query_level=0 failed"); + + torture_comment(tctx, "Testing LogonGetCapabilities with query_level=3\n"); + + r.in.query_level = 3; + ZERO_STRUCT(return_auth); + + /* + * we need to operate on a temporary copy of creds + * because dcerpc_netr_LogonGetCapabilities with + * an unknown query level returns DCERPC_NCA_S_FAULT_INVALID_TAG + * => NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE + * without looking a the authenticator. + */ + tmp_creds = *creds; + netlogon_creds_client_authenticator(&tmp_creds, &auth); + + status = dcerpc_netr_LogonGetCapabilities_r(b, tctx, &r); + torture_assert_ntstatus_equal(tctx, status, NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE, + "LogonGetCapabilities query_level=0 failed"); + + torture_comment(tctx, "Testing LogonGetCapabilities with query_level=1\n"); + + r.in.query_level = 1; ZERO_STRUCT(return_auth); /* @@ -2077,6 +2116,42 @@ *creds = tmp_creds; + torture_assert(tctx, netlogon_creds_client_check(creds, + &r.out.return_authenticator->cred), + "Credential chaining failed"); + + torture_assert_int_equal(tctx, creds->negotiate_flags, + capabilities.server_capabilities, + "negotiate flags"); + + torture_comment(tctx, "Testing LogonGetCapabilities with query_level=2\n"); + + r.in.query_level = 2; + ZERO_STRUCT(return_auth); + + /* + * we need to operate on a temporary copy of creds + * because dcerpc_netr_LogonGetCapabilities with + * an query level 2 may returns DCERPC_NCA_S_FAULT_INVALID_TAG + * => NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE + * without looking a the authenticator. + */ + tmp_creds = *creds; + netlogon_creds_client_authenticator(&tmp_creds, &auth); + + status = dcerpc_netr_LogonGetCapabilities_r(b, tctx, &r); + if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE)) { + /* + * an server without KB5028166 returns + * DCERPC_NCA_S_FAULT_INVALID_TAG => + * NT_STATUS_RPC_ENUM_VALUE_OUT_OF_RANGE + */ + return true; + } + torture_assert_ntstatus_ok(tctx, status, "LogonGetCapabilities query_level=2 failed"); + + *creds = tmp_creds; + torture_assert(tctx, netlogon_creds_client_check(creds, &r.out.return_authenticator->cred), "Credential chaining failed"); diff -Nru samba-4.17.9+dfsg/source4/torture/smb2/session.c samba-4.17.10+dfsg/source4/torture/smb2/session.c --- samba-4.17.9+dfsg/source4/torture/smb2/session.c 2022-08-08 14:15:40.488200400 +0000 +++ samba-4.17.10+dfsg/source4/torture/smb2/session.c 2023-07-14 13:15:04.453269700 +0000 @@ -5498,3 +5498,67 @@ return suite; } + +static bool test_session_require_sign_bug15397(struct torture_context *tctx, + struct smb2_tree *_tree) +{ + const char *host = torture_setting_string(tctx, "host", NULL); + const char *share = torture_setting_string(tctx, "share", NULL); + struct cli_credentials *_creds = samba_cmdline_get_creds(); + struct cli_credentials *creds = NULL; + struct smbcli_options options; + struct smb2_tree *tree = NULL; + uint8_t security_mode; + NTSTATUS status; + bool ok = true; + + /* + * Setup our own connection so we can control the signing flags + */ + + creds = cli_credentials_shallow_copy(tctx, _creds); + torture_assert(tctx, creds != NULL, "cli_credentials_shallow_copy"); + + options = _tree->session->transport->options; + options.client_guid = GUID_random(); + options.signing = SMB_SIGNING_IF_REQUIRED; + + status = smb2_connect(tctx, + host, + lpcfg_smb_ports(tctx->lp_ctx), + share, + lpcfg_resolve_context(tctx->lp_ctx), + creds, + &tree, + tctx->ev, + &options, + lpcfg_socket_options(tctx->lp_ctx), + lpcfg_gensec_settings(tctx, tctx->lp_ctx)); + torture_assert_ntstatus_ok_goto(tctx, status, ok, done, + "smb2_connect failed"); + + security_mode = smb2cli_session_security_mode(tree->session->smbXcli); + + torture_assert_int_equal_goto( + tctx, + security_mode, + SMB2_NEGOTIATE_SIGNING_REQUIRED | SMB2_NEGOTIATE_SIGNING_ENABLED, + ok, + done, + "Signing not required"); + +done: + return ok; +} + +struct torture_suite *torture_smb2_session_req_sign_init(TALLOC_CTX *ctx) +{ + struct torture_suite *suite = + torture_suite_create(ctx, "session-require-signing"); + + torture_suite_add_1smb2_test(suite, "bug15397", + test_session_require_sign_bug15397); + + suite->description = talloc_strdup(suite, "SMB2-SESSION require signing tests"); + return suite; +} diff -Nru samba-4.17.9+dfsg/source4/torture/smb2/smb2.c samba-4.17.10+dfsg/source4/torture/smb2/smb2.c --- samba-4.17.9+dfsg/source4/torture/smb2/smb2.c 2023-01-26 17:45:01.665668500 +0000 +++ samba-4.17.10+dfsg/source4/torture/smb2/smb2.c 2023-07-14 13:15:04.457269700 +0000 @@ -189,6 +189,7 @@ torture_suite_add_suite(suite, torture_smb2_sharemode_init(suite)); torture_suite_add_1smb2_test(suite, "hold-oplock", test_smb2_hold_oplock); torture_suite_add_suite(suite, torture_smb2_session_init(suite)); + torture_suite_add_suite(suite, torture_smb2_session_req_sign_init(suite)); torture_suite_add_suite(suite, torture_smb2_replay_init(suite)); torture_suite_add_simple_test(suite, "dosmode", torture_smb2_dosmode); torture_suite_add_simple_test(suite, "async_dosmode", torture_smb2_async_dosmode);