The branch, master has been updated via b145434f24f smbXsrv_client: move the connection passing to smb2srv_client_mc_negprot_send/recv via f1f5c36581a smbd: make sure that xconn is alive for the lifetime of smbXsrv_connection_shutdown_send/recv via 2a0626c32ae s4:torture/smb2: add smb2.lease.timeout-disconnect test via 638c4435a0e smbXsrv_session: set session->db_rec = NULL after session->db_rec = local_rec via 253a4de82bd smbXsrv_tcon: explicitly set tcon->db_rec = NULL after tcon->db_rec = local_rec via 2cf1628419f s4:torture/smb2: add a smb2.session.two_logoff test via 106121a91b5 smbd: introduce a smbXsrv_connection_destructor() via c9ff08649f3 smbd: improve smbXsrv_connection_dbg() for debugging multi-channel problems via c784f8c9aba selftest: enable 'server multi channel support = yes' via a200769950d s4:torture/smb2: use %t (timestamp) instead of %R for lease.dynamic_share test via 18818dba00d smbd: let smbd_request_guid() use smb1req->xconn->channel_id via 927346d93e4 docs-xml: clarify "smb2 disable lock sequence checking" section via e0426187eb3 dsdb: Fix CID 1473454: Null pointer dereferences via 84be21565c8 dsdb: Fix CID 1473453: Null pointer dereferences via 7d2faa2714f librpc: Lower dcesrv_call_dispatch_local() errors from DBG_ERR to DBG_INFO via 5fe7536145d winbind: Remove noisy error message in wb_open_internal_pipe() from 654c18a244f g_lock: Fix uninitalized variable reads
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit b145434f24f35a3d43d49980ef10bf59aae9243d Author: Stefan Metzmacher <me...@samba.org> Date: Mon Jul 6 17:27:05 2020 +0200 smbXsrv_client: move the connection passing to smb2srv_client_mc_negprot_send/recv We need a full request/response pair in order to avoid races in the multichannel connection passing. smb2srv_client_mc_negprot_send/recv locks the db record for the given client_guid. If there's no entry found, we add ourself and return NT_STATUS_OK. If there's an existing process for that client guid we start messaging_filtered_read_send() dbwrap_watched_watch_send() before calling smb2srv_client_connection_pass(). Then we release the lock and wait for either MSG_SMBXSRV_CONNECTION_PASSED to arrive or retry if dbwrap_watched_watch_recv signaled a change in the database. If we got MSG_SMBXSRV_CONNECTION_PASSED we'll return NT_STATUS_MESSAGE_RETRIEVED in order to signal that the other process will take care of the connection and we terminate the current process. All that is done completely async, which means that the IDLE_CLOSED_TIMEOUT (60 seconds) may trigger deadtime_fn(), which will send itself a MSG_SHUTDOWN. So the process that accepted the tcp connection exists if there was no MSG_SMBXSRV_CONNECTION_PASSED within 60 seconds. However the fd may still exists in the kernel (and the new connection may still be handed to the other process. If that process somehow exists before there's no way to prevent a connection termination for the client. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14433 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> Autobuild-User(master): Jeremy Allison <j...@samba.org> Autobuild-Date(master): Sat Mar 6 03:30:06 UTC 2021 on sn-devel-184 commit f1f5c36581a942bcccd63ede4b023fdb1a1d3ed4 Author: Stefan Metzmacher <me...@samba.org> Date: Wed Sep 23 13:07:20 2020 +0200 smbd: make sure that xconn is alive for the lifetime of smbXsrv_connection_shutdown_send/recv BUG: https://bugzilla.samba.org/show_bug.cgi?id=14533 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 2a0626c32ae2803cb6c478717c34bf30231dc3dc Author: Stefan Metzmacher <me...@samba.org> Date: Wed Sep 23 04:58:22 2020 +0200 s4:torture/smb2: add smb2.lease.timeout-disconnect test This reproduces a problem that is triggered when smbd_server_connection_terminate() is called recursively. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14533 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 638c4435a0eeb110719dd2e799f2a12758667326 Author: Stefan Metzmacher <me...@samba.org> Date: Wed Sep 23 06:00:28 2020 +0200 smbXsrv_session: set session->db_rec = NULL after session->db_rec = local_rec This actually fixes crashes due to stale pointers. With multi-channel and with 2 (or more) connections, we'll call smbXsrv_session_disconnect_xconn() when a connection gets disconnected, but we'll leave smbXsrv_client and all other connections in place. However smbXsrv_session_disconnect_xconn_callback() left a stale session->db_rec pointer in place, which means a following smbXsrv_session_logoff() will call dbwrap_record_delete(local_rec) on a stale pointer. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14532 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 253a4de82bd4e44586572b71e06762c3f6dbd795 Author: Stefan Metzmacher <me...@samba.org> Date: Wed Sep 23 11:24:46 2020 +0200 smbXsrv_tcon: explicitly set tcon->db_rec = NULL after tcon->db_rec = local_rec There's no know problem that we fix for the smbXsrv_tcon_disconnect_all_callback() case, but it might prevent future problems. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14532 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 2cf1628419f5035107d1be6d7ab1bf6533bad7a2 Author: Stefan Metzmacher <me...@samba.org> Date: Wed Sep 23 13:49:27 2020 +0200 s4:torture/smb2: add a smb2.session.two_logoff test This reproduces a bug where two SMB2_LOGOFF messages kill the whole client smbd when multi-channel is used, instead of just removing the logical session. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14532 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 106121a91b5108bfcc48f641385cd99e7dab7006 Author: Stefan Metzmacher <me...@samba.org> Date: Wed Sep 23 13:13:22 2020 +0200 smbd: introduce a smbXsrv_connection_destructor() For now it only prints a debug message, but that's already very useful for multi-channel debugging. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14534 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit c9ff08649f3c9f8bb5896a0c0a70fbcdf856c9d5 Author: Stefan Metzmacher <me...@samba.org> Date: Wed Sep 23 13:13:01 2020 +0200 smbd: improve smbXsrv_connection_dbg() for debugging multi-channel problems BUG: https://bugzilla.samba.org/show_bug.cgi?id=14534 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit c784f8c9aba185bb803c23b166374bdce9550203 Author: Stefan Metzmacher <me...@samba.org> Date: Fri Jun 19 12:32:59 2020 +0200 selftest: enable 'server multi channel support = yes' BUG: https://bugzilla.samba.org/show_bug.cgi?id=14534 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit a200769950dbf57f5d493e86b64ec1db964f00c7 Author: Stefan Metzmacher <me...@samba.org> Date: Tue Feb 9 16:54:18 2021 +0100 s4:torture/smb2: use %t (timestamp) instead of %R for lease.dynamic_share test This test should be independent of the protocol in order to be independent of multi-channel support of the server. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14534 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 18818dba00db4d9cfccf58f86ef0764145a654da Author: Stefan Metzmacher <me...@samba.org> Date: Tue Jul 28 12:11:38 2020 +0200 smbd: let smbd_request_guid() use smb1req->xconn->channel_id The unique identifier of a channel/connection is the channel_id, the pointer of 'xconn' can be reused. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14534 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 927346d93e4d241c588a22405038b8fa2ccc261d Author: Stefan Metzmacher <me...@samba.org> Date: Thu Aug 27 04:50:15 2020 +0200 docs-xml: clarify "smb2 disable lock sequence checking" section BUG: https://bugzilla.samba.org/show_bug.cgi?id=14534 Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit e0426187eb3b5ef319c4ac8c5cf7442abbc0b0b5 Author: Volker Lendecke <v...@samba.org> Date: Tue Mar 2 11:30:44 2021 +0100 dsdb: Fix CID 1473454: Null pointer dereferences Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 84be21565c892289e133895da5999085f3641a17 Author: Volker Lendecke <v...@samba.org> Date: Tue Mar 2 11:27:07 2021 +0100 dsdb: Fix CID 1473453: Null pointer dereferences Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 7d2faa2714f83998673bf2fb874ce8202a09879b Author: Samuel Cabrero <scabr...@samba.org> Date: Mon Mar 1 17:26:24 2021 +0100 librpc: Lower dcesrv_call_dispatch_local() errors from DBG_ERR to DBG_INFO Before merging the s3 and s4 RPC servers the rpcint_dispatch function was not logging any error. This commit lowers from DBG_ERR to DBG_INFO the importance of error messages when dispatching local RPC calls. There are some situations where RPC functions return RPC faults and this is not a fatal condition. One example is _lsa_QueryInfoPolicy2. This change prevents a noisy error logged when winbindd tries to connect to its primary domain in the nt4_member and ad_member test environments: [2021/03/01 16:49:38.486111, 0, pid=12456] ../../librpc/rpc/dcesrv_core.c:2990(dcesrv_call_dispatch_local) dcesrv_call_dispatch_local: DCE/RPC fault in call lsarpc:2E - DCERPC_NCA_S_OP_RNG_ERROR Signed-off-by: Samuel Cabrero <scabr...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> commit 5fe7536145dc2c29ec71f6077188d74f4e08abd6 Author: Samuel Cabrero <scabr...@samba.org> Date: Mon Mar 1 15:56:06 2021 +0100 winbind: Remove noisy error message in wb_open_internal_pipe() Before merging the s4 and s3 RPC servers the make_internal_rpc_pipe_p() function did not fail when the requested interface was not registered in the calling process because it did not check the return value of rpc_srv_get_pipe_cmds(). If the interface was not registed, the pointer to the interface functions was NULL and later, when dispatching a call, rpcint_dispatch() returned NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE in this case. After merging the RPC servers, the rpc_pipe_open_internal() function will return NT_STATUS_RPC_INTERFACE_NOT_FOUND if the interface is not registered in the calling process. This causes a noisy error message in winbind when it tries to open the dssetup pipe to the primary domain and it is not an AD domain. The callers of wb_open_internal_pipe() when connecting to the domain already logs the error at level greather or equal to five. This commit moves the dupplicated and noisy error message at level zero from wb_open_internal_pipe() to its callers outside winbindd_cm.c. This error can be seen in winbindd logs of ad_member and nt4_member test environments. [2021/03/01 16:49:38.486004, 0, pid=12456] ../../source3/winbindd/winbindd_cm.c:1893(wb_open_internal_pipe) open_internal_pipe: Could not connect to dssetup pipe: NT_STATUS_RPC_INTERFACE_NOT_FOUND Signed-off-by: Samuel Cabrero <scabr...@samba.org> Reviewed-by: Jeremy Allison <j...@samba.org> ----------------------------------------------------------------------- Summary of changes: .../smb2_disable_lock_sequence_checking.xml | 2 +- librpc/idl/messaging.idl | 1 + librpc/rpc/dcesrv_core.c | 32 +- selftest/knownfail | 4 - selftest/knownfail.d/multichannel | 7 + selftest/target/Samba3.pm | 10 +- selftest/target/Samba4.pm | 4 + source3/librpc/idl/smbXsrv.idl | 8 +- source3/smbd/globals.c | 2 +- source3/smbd/globals.h | 12 +- source3/smbd/process.c | 20 +- source3/smbd/smb2_negprot.c | 110 +++-- source3/smbd/smb2_server.c | 31 ++ source3/smbd/smbXsrv_client.c | 471 ++++++++++++++++----- source3/smbd/smbXsrv_session.c | 10 +- source3/smbd/smbXsrv_tcon.c | 1 + source3/winbindd/winbindd_cm.c | 2 - source3/winbindd/winbindd_samr.c | 4 + source4/dsdb/samdb/ldb_modules/operational.c | 4 + source4/dsdb/samdb/ldb_modules/rootdse.c | 10 +- source4/torture/smb2/lease.c | 240 ++++++++--- source4/torture/smb2/session.c | 43 ++ 22 files changed, 802 insertions(+), 226 deletions(-) create mode 100644 selftest/knownfail.d/multichannel Changeset truncated at 500 lines: diff --git a/docs-xml/smbdotconf/protocol/smb2_disable_lock_sequence_checking.xml b/docs-xml/smbdotconf/protocol/smb2_disable_lock_sequence_checking.xml index 9ca7187fb51..3a33b8b1420 100644 --- a/docs-xml/smbdotconf/protocol/smb2_disable_lock_sequence_checking.xml +++ b/docs-xml/smbdotconf/protocol/smb2_disable_lock_sequence_checking.xml @@ -22,7 +22,7 @@ in [MS-SMB2].</para> <para>By default Samba behaves according to the specification - and sends smb2 oplock break notification retries.</para> + and implements lock sequence checking when multi-channel is used.</para> <para>Warning: Only enable this option if existing clients can't handle lock sequence checking for handles without Open.IsResilient and Open.IsPersistent. diff --git a/librpc/idl/messaging.idl b/librpc/idl/messaging.idl index 8160c76149c..06a72520f8b 100644 --- a/librpc/idl/messaging.idl +++ b/librpc/idl/messaging.idl @@ -136,6 +136,7 @@ interface messaging /* smbXsrv messages */ MSG_SMBXSRV_SESSION_CLOSE = 0x0600, MSG_SMBXSRV_CONNECTION_PASS = 0x0601, + MSG_SMBXSRV_CONNECTION_PASSED = 0x0602, /* source4 and NTVFS smb server messages */ MSG_BRL_RETRY = 0x0700, diff --git a/librpc/rpc/dcesrv_core.c b/librpc/rpc/dcesrv_core.c index a51467c87c0..7a20ffe71a0 100644 --- a/librpc/rpc/dcesrv_core.c +++ b/librpc/rpc/dcesrv_core.c @@ -2978,19 +2978,19 @@ _PUBLIC_ NTSTATUS dcesrv_call_dispatch_local(struct dcesrv_call_state *call) /* unravel the NDR for the packet */ status = call->context->iface->ndr_pull(call, call, pull, &call->r); if (!NT_STATUS_IS_OK(status)) { - DBG_ERR("DCE/RPC fault in call %s:%02X - %s\n", - call->context->iface->name, - call->pkt.u.request.opnum, - dcerpc_errstr(call, call->fault_code)); + DBG_INFO("DCE/RPC fault in call %s:%02X - %s\n", + call->context->iface->name, + call->pkt.u.request.opnum, + dcerpc_errstr(call, call->fault_code)); return dcerpc_fault_to_nt_status(call->fault_code); } status = call->context->iface->local(call, call, call->r); if (!NT_STATUS_IS_OK(status)) { - DBG_ERR("DCE/RPC fault in call %s:%02X - %s\n", - call->context->iface->name, - call->pkt.u.request.opnum, - dcerpc_errstr(call, call->fault_code)); + DBG_INFO("DCE/RPC fault in call %s:%02X - %s\n", + call->context->iface->name, + call->pkt.u.request.opnum, + dcerpc_errstr(call, call->fault_code)); return dcerpc_fault_to_nt_status(call->fault_code); } @@ -3000,10 +3000,10 @@ _PUBLIC_ NTSTATUS dcesrv_call_dispatch_local(struct dcesrv_call_state *call) /* call the reply function */ status = call->context->iface->reply(call, call, call->r); if (!NT_STATUS_IS_OK(status)) { - DBG_ERR("DCE/RPC fault in call %s:%02X - %s\n", - call->context->iface->name, - call->pkt.u.request.opnum, - dcerpc_errstr(call, call->fault_code)); + DBG_INFO("DCE/RPC fault in call %s:%02X - %s\n", + call->context->iface->name, + call->pkt.u.request.opnum, + dcerpc_errstr(call, call->fault_code)); return dcerpc_fault_to_nt_status(call->fault_code); } @@ -3016,10 +3016,10 @@ _PUBLIC_ NTSTATUS dcesrv_call_dispatch_local(struct dcesrv_call_state *call) status = call->context->iface->ndr_push(call, call, push, call->r); if (!NT_STATUS_IS_OK(status)) { - DBG_ERR("DCE/RPC fault in call %s:%02X - %s\n", - call->context->iface->name, - call->pkt.u.request.opnum, - dcerpc_errstr(call, call->fault_code)); + DBG_INFO("DCE/RPC fault in call %s:%02X - %s\n", + call->context->iface->name, + call->pkt.u.request.opnum, + dcerpc_errstr(call, call->fault_code)); return dcerpc_fault_to_nt_status(call->fault_code); } diff --git a/selftest/knownfail b/selftest/knownfail index 6c005d1f4de..6a760d6c6e0 100644 --- a/selftest/knownfail +++ b/selftest/knownfail @@ -213,14 +213,10 @@ ^samba3.smb2.session.*reauth5 # some special anonymous checks? ^samba3.smb2.compound.interim2 # wrong return code (STATUS_CANCELLED) ^samba3.smb2.compound.aio.interim2 # wrong return code (STATUS_CANCELLED) -^samba3.smb2.replay.replay3 # This requires multi-chanel -^samba3.smb2.replay.replay4 # This requires multi-chanel -^samba3.smb2.lock.replay_smb3_specification_multi # This requires multi-chanel ^samba3.smb2.lock.replay_smb3_specification_durable\(nt4_dc\) # Requires durable handles ^samba3.smb2.lock.*replay_broken_windows # This tests the windows behaviour ^samba3.smb2.lease.statopen3 ^samba3.smb2.lease.unlink # we currently do not downgrade RH lease to R after unlink -^samba3.smb2.multichannel ^samba4.smb2.ioctl.compress_notsup.*\(ad_dc_ntvfs\) ^samba3.raw.session.*reauth2 # maybe fix this? ^samba3.rpc.lsa.secrets.seal # This gives NT_STATUS_LOCAL_USER_SESSION_KEY diff --git a/selftest/knownfail.d/multichannel b/selftest/knownfail.d/multichannel new file mode 100644 index 00000000000..6c91b552c0d --- /dev/null +++ b/selftest/knownfail.d/multichannel @@ -0,0 +1,7 @@ +^samba3.smb2.multichannel.oplocks.test2.nt4_dc # expects windows behavior => smb2 disable oplock break retry = yes +^samba3.smb2.multichannel.oplocks.test3_windows.nt4_dc # expects windows behavior => smb2 disable oplock break retry = yes +^samba3.smb2.multichannel.oplocks.test3_specification.ad_dc # expects samba (MS-SMB2) behavior +^samba3.smb2.multichannel.leases.test1.ad_dc # requires lease support +^samba3.smb2.multichannel.leases.test2.ad_dc # requires lease support +^samba3.smb2.multichannel.leases.test3.ad_dc # requires lease support +^samba3.smb2.multichannel.leases.test4.ad_dc # requires lease support diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm index b0910433940..a0c43aa842e 100755 --- a/selftest/target/Samba3.pm +++ b/selftest/target/Samba3.pm @@ -2075,12 +2075,9 @@ sub provision($$) my $badnames_shrdir="$shrdir/badnames"; push(@dirs,$badnames_shrdir); - my $lease1_shrdir="$shrdir/SMB2_10"; + my $lease1_shrdir="$shrdir/dynamic"; push(@dirs,$lease1_shrdir); - my $lease2_shrdir="$shrdir/SMB3_00"; - push(@dirs,$lease2_shrdir); - my $manglenames_shrdir="$shrdir/manglenames"; push(@dirs,$manglenames_shrdir); @@ -2287,6 +2284,8 @@ sub provision($$) client min protocol = SMB2_02 server min protocol = SMB2_02 + server multi channel support = yes + workgroup = $domain private dir = $privatedir @@ -2652,8 +2651,9 @@ sub provision($$) guest ok = yes [dynamic_share] - path = $shrdir/%R + path = $shrdir/dynamic/%t guest ok = yes + root preexec = mkdir %P [widelinks_share] path = $widelinks_shrdir diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm index dff9d042be9..61e9eb61422 100755 --- a/selftest/target/Samba4.pm +++ b/selftest/target/Samba4.pm @@ -763,6 +763,8 @@ sub provision_raw_step1($$) tls crlfile = ${crlfile} tls verify peer = no_check panic action = $RealBin/gdb_backtrace \%d + smbd:suicide mode = yes + smbd:FSCTL_SMBTORTURE = yes wins support = yes server role = $ctx->{server_role} server services = +echo $services @@ -1905,6 +1907,8 @@ sub provision_ad_dc($$$$$$$) kernel oplocks = no kernel change notify = no smb2 leases = no + smb2 disable oplock break retry = yes + server multi channel support = yes logging = file printing = bsd diff --git a/source3/librpc/idl/smbXsrv.idl b/source3/librpc/idl/smbXsrv.idl index 78fc3644d2f..09e3ca351f3 100644 --- a/source3/librpc/idl/smbXsrv.idl +++ b/source3/librpc/idl/smbXsrv.idl @@ -167,11 +167,15 @@ interface smbXsrv /* * smbXsrv_connection_pass is used in the MSG_SMBXSRV_CONNECTION_PASS - * message + * message and echo'ed as MSG_SMBXSRV_CONNECTION_PASSED message with + * negotiate_request.length = 0. */ typedef struct { - NTTIME initial_connect_time; GUID client_guid; + server_id src_server_id; + NTTIME xconn_connect_time; + server_id dst_server_id; + NTTIME client_connect_time; DATA_BLOB negotiate_request; } smbXsrv_connection_pass0; diff --git a/source3/smbd/globals.c b/source3/smbd/globals.c index c0fafecd2eb..4d4553649c0 100644 --- a/source3/smbd/globals.c +++ b/source3/smbd/globals.c @@ -120,7 +120,7 @@ struct GUID smbd_request_guid(struct smb_request *smb1req, uint16_t idx) v.time_mid = (uint16_t)(uintptr_t)smb1req->vwv; } - SBVAL((uint8_t *)&v, 8, (uintptr_t)smb1req->xconn); + SBVAL((uint8_t *)&v, 8, smb1req->xconn->channel_id); return v; } diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 4685b6971d3..d1a2c6204ba 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -367,6 +367,7 @@ struct smbXsrv_connection { struct { NTSTATUS status; + bool terminating; int sock; struct tevent_fd *fde; @@ -549,14 +550,11 @@ NTSTATUS smbXsrv_client_create(TALLOC_CTX *mem_ctx, struct messaging_context *msg_ctx, NTTIME now, struct smbXsrv_client **_client); -NTSTATUS smbXsrv_client_update(struct smbXsrv_client *client); NTSTATUS smbXsrv_client_remove(struct smbXsrv_client *client); -NTSTATUS smb2srv_client_lookup_global(struct smbXsrv_client *client, - struct GUID client_guid, - TALLOC_CTX *mem_ctx, - struct smbXsrv_client_global0 **_pass); -NTSTATUS smb2srv_client_connection_pass(struct smbd_smb2_request *smb2req, - struct smbXsrv_client_global0 *global); +struct tevent_req *smb2srv_client_mc_negprot_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct smbd_smb2_request *smb2req); +NTSTATUS smb2srv_client_mc_negprot_recv(struct tevent_req *req); NTSTATUS smbXsrv_connection_init_tables(struct smbXsrv_connection *conn, enum protocol_types protocol); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 9e861554fa7..03409742752 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -3745,19 +3745,32 @@ static void smbd_tevent_trace_callback(enum tevent_trace_point point, const char *smbXsrv_connection_dbg(const struct smbXsrv_connection *xconn) { const char *ret; - + char *addr; /* * TODO: this can be improved later * maybe including the client guid or more */ - ret = tsocket_address_string(xconn->remote_address, talloc_tos()); - if (ret == NULL) { + addr = tsocket_address_string(xconn->remote_address, talloc_tos()); + if (addr == NULL) { return "<tsocket_address_string() failed>"; } + ret = talloc_asprintf(talloc_tos(), "ptr=%p,id=%llu,addr=%s", + xconn, (unsigned long long)xconn->channel_id, addr); + TALLOC_FREE(addr); + if (ret == NULL) { + return "<talloc_asprintf() failed>"; + } + return ret; } +static int smbXsrv_connection_destructor(struct smbXsrv_connection *xconn) +{ + DBG_DEBUG("xconn[%s]\n", smbXsrv_connection_dbg(xconn)); + return 0; +} + NTSTATUS smbd_add_connection(struct smbXsrv_client *client, int sock_fd, NTTIME now, struct smbXsrv_connection **_xconn) { @@ -3788,6 +3801,7 @@ NTSTATUS smbd_add_connection(struct smbXsrv_client *client, int sock_fd, TALLOC_FREE(frame); return NT_STATUS_NO_MEMORY; } + talloc_set_destructor(xconn, smbXsrv_connection_destructor); talloc_steal(frame, xconn); xconn->client = client; xconn->connect_time = now; diff --git a/source3/smbd/smb2_negprot.c b/source3/smbd/smb2_negprot.c index 99303f1b07b..0cd093d1eba 100644 --- a/source3/smbd/smb2_negprot.c +++ b/source3/smbd/smb2_negprot.c @@ -127,10 +127,19 @@ enum protocol_types smbd_smb2_protocol_dialect_match(const uint8_t *indyn, return PROTOCOL_NONE; } +struct smbd_smb2_request_process_negprot_state { + struct smbd_smb2_request *req; + DATA_BLOB outbody; + DATA_BLOB outdyn; +}; + +static void smbd_smb2_request_process_negprot_mc_done(struct tevent_req *subreq); + NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req) { + struct smbd_smb2_request_process_negprot_state *state = NULL; struct smbXsrv_connection *xconn = req->xconn; - struct smbXsrv_client_global0 *global0 = NULL; + struct tevent_req *subreq = NULL; NTSTATUS status; const uint8_t *inbody; const uint8_t *indyn = NULL; @@ -675,38 +684,83 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req) return smbd_smb2_request_done(req, outbody, &outdyn); } - status = smb2srv_client_lookup_global(xconn->client, - xconn->smb2.client.guid, - req, &global0); - /* - * TODO: check for races... - */ - if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECTID_NOT_FOUND)) { + state = talloc_zero(req, struct smbd_smb2_request_process_negprot_state); + if (state == NULL) { + return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY); + } + *state = (struct smbd_smb2_request_process_negprot_state) { + .req = req, + .outbody = outbody, + .outdyn = outdyn, + }; + + subreq = smb2srv_client_mc_negprot_send(state, + req->xconn->client->raw_ev_ctx, + req); + if (subreq == NULL) { + return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY); + } + tevent_req_set_callback(subreq, + smbd_smb2_request_process_negprot_mc_done, + state); + return NT_STATUS_OK; +} + +static void smbd_smb2_request_process_negprot_mc_done(struct tevent_req *subreq) +{ + struct smbd_smb2_request_process_negprot_state *state = + tevent_req_callback_data(subreq, + struct smbd_smb2_request_process_negprot_state); + struct smbd_smb2_request *req = state->req; + struct smbXsrv_connection *xconn = req->xconn; + NTSTATUS status; + + status = smb2srv_client_mc_negprot_recv(subreq); + TALLOC_FREE(subreq); + if (NT_STATUS_EQUAL(status, NT_STATUS_MESSAGE_RETRIEVED)) { /* - * This stores the new client information in - * smbXsrv_client_global.tdb + * The connection was passed to another process */ - xconn->client->global->client_guid = - xconn->smb2.client.guid; - status = smbXsrv_client_update(xconn->client); - if (!NT_STATUS_IS_OK(status)) { - return status; + smbd_server_connection_terminate(xconn, + "passed connection"); + /* + * smbd_server_connection_terminate() should not return! + */ + smb_panic(__location__); + return; + } + if (!NT_STATUS_IS_OK(status)) { + status = smbd_smb2_request_error(req, status); + if (NT_STATUS_IS_OK(status)) { + return; } - xconn->smb2.client.guid_verified = true; - } else if (NT_STATUS_IS_OK(status)) { - status = smb2srv_client_connection_pass(req, - global0); - if (!NT_STATUS_IS_OK(status)) { - return smbd_smb2_request_error(req, status); - } + /* + * The connection was passed to another process + */ + smbd_server_connection_terminate(xconn, nt_errstr(status)); + /* + * smbd_server_connection_terminate() should not return! + */ + smb_panic(__location__); + return; + } - smbd_server_connection_terminate(xconn, - "passed connection"); - return NT_STATUS_OBJECTID_EXISTS; - } else { - return smbd_smb2_request_error(req, status); + /* + * We're the first connection... + */ + status = smbd_smb2_request_done(req, state->outbody, &state->outdyn); + if (NT_STATUS_IS_OK(status)) { + return; } - return smbd_smb2_request_done(req, outbody, &outdyn); + /* + * The connection was passed to another process + */ + smbd_server_connection_terminate(xconn, nt_errstr(status)); + /* + * smbd_server_connection_terminate() should not return! + */ + smb_panic(__location__); + return; } diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index 1322cf3ba08..bd0eab00606 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -1500,6 +1500,7 @@ size_t smbXsrv_client_valid_connections(struct smbXsrv_client *client) struct smbXsrv_connection_shutdown_state { struct tevent_queue *wait_queue; + struct smbXsrv_connection *xconn; }; static void smbXsrv_connection_shutdown_wait_done(struct tevent_req *subreq); @@ -1520,6 +1521,7 @@ static struct tevent_req *smbXsrv_connection_shutdown_send(TALLOC_CTX *mem_ctx, * smbXsrv_connection_disconnect_transport() before. */ SMB_ASSERT(!NT_STATUS_IS_OK(xconn->transport.status)); + SMB_ASSERT(xconn->transport.terminating); req = tevent_req_create(mem_ctx, &state, struct smbXsrv_connection_shutdown_state); @@ -1527,6 +1529,9 @@ static struct tevent_req *smbXsrv_connection_shutdown_send(TALLOC_CTX *mem_ctx, return NULL; } + state->xconn = xconn; + tevent_req_defer_callback(req, ev); + status = smbXsrv_session_disconnect_xconn(xconn); if (tevent_req_nterror(req, status)) { return tevent_req_post(req, ev); @@ -1590,15 +1595,33 @@ static void smbXsrv_connection_shutdown_wait_done(struct tevent_req *subreq) struct tevent_req *req = tevent_req_callback_data(subreq, struct tevent_req); + struct smbXsrv_connection_shutdown_state *state = + tevent_req_data(req, + struct smbXsrv_connection_shutdown_state); + struct smbXsrv_connection *xconn = state->xconn; tevent_queue_wait_recv(subreq); TALLOC_FREE(subreq); tevent_req_done(req); + /* + * make sure the xconn pointer is still valid, + * it should as we used tevent_req_defer_callback() + */ + SMB_ASSERT(xconn->transport.terminating); } static NTSTATUS smbXsrv_connection_shutdown_recv(struct tevent_req *req) { + struct smbXsrv_connection_shutdown_state *state = + tevent_req_data(req, + struct smbXsrv_connection_shutdown_state); + struct smbXsrv_connection *xconn = state->xconn; + /* + * make sure the xconn pointer is still valid, + * it should as we used tevent_req_defer_callback() + */ + SMB_ASSERT(xconn->transport.terminating); return tevent_req_simple_recv_ntstatus(req); } @@ -1637,6 +1660,14 @@ void smbd_server_connection_terminate_ex(struct smbXsrv_connection *xconn, num_ok = smbXsrv_client_valid_connections(client); + if (xconn->transport.terminating) { + DBG_DEBUG("skip recursion conn[%s] num_ok[%zu] reason[%s] at %s\n", + smbXsrv_connection_dbg(xconn), num_ok, -- Samba Shared Repository