[SCM] Samba Shared Repository - branch v4-16-test updated

Jule Anger janger at samba.org
Tue Oct 18 09:42:01 UTC 2022


The branch, v4-16-test has been updated
       via  3e0ce4513b0 vfs_fruit: add missing calls to tevent_req_received()
       via  6c7af405580 s3: VFS: fruit. Implement fsync_send()/fsync_recv().
       via  24bc377a0ec s4: smbtorture: Add fsync_resource_fork test to fruit tests.
       via  b3e8e8185fc smbXsrv_client: handle NAME_NOT_FOUND from smb2srv_client_connection_{pass,drop}()
       via  0fa03f112f7 smbXsrv_client: make sure we only wait for smb2srv_client_mc_negprot_filter once and only when needed
       via  935f1ec476e smbXsrv_client: call smb2srv_client_connection_{pass,drop}() before dbwrap_watched_watch_send()
       via  68a233322bd smbXsrv_client: fix a debug message in smbXsrv_client_global_verify_record()
       via  f806366dd4a smbXsrv_client: ignore NAME_NOT_FOUND from smb2srv_client_connection_passed
       via  52dd57d4b30 smbXsrv_client: notify a different node to drop a connection by client guid.
       via  ada5ef9d847 smbXsrv_client: correctly check in negotiate_request.length smbXsrv_client_connection_pass[ed]_*
      from  1a4d3a2db79 python-drs: Add client-side debug and fallback for GET_ANC

https://git.samba.org/?p=samba.git;a=shortlog;h=v4-16-test


- Log -----------------------------------------------------------------
commit 3e0ce4513b06f17791c02ab0b4f787f63fe69b9f
Author: Ralph Boehme <slow at samba.org>
Date:   Thu Oct 6 14:31:08 2022 +0200

    vfs_fruit: add missing calls to tevent_req_received()
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15182
    
    Signed-off-by: Ralph Boehme <slow at samba.org>
    Reviewed-by: Ralph Böhme <slow at samba.org>
    (cherry picked from commit a7fba3ff5996330158d3cc6bc24746a59492b690)
    
    Autobuild-User(v4-16-test): Jule Anger <janger at samba.org>
    Autobuild-Date(v4-16-test): Tue Oct 18 09:41:37 UTC 2022 on sn-devel-184

commit 6c7af4055805041726c5735da5b89f2f7f067aef
Author: Jeremy Allison <jra at samba.org>
Date:   Tue Sep 20 13:25:22 2022 -0700

    s3: VFS: fruit. Implement fsync_send()/fsync_recv().
    
    For type == ADOUBLE_META, fio->fake_fd is true so
    writes are already synchronous, just call tevent_req_post().
    
    For type == ADOUBLE_RSRC we know we are configured
    with FRUIT_RSRC_ADFILE (because fruit_must_handle_aio_stream()
    returned true), so we can just call SMB_VFS_NEXT_FSYNC_SEND()
    after replacing fsp with fio->ad_fsp.
    
    Remove knownfail.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15182
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Ralph Böhme <slow at samba.org>
    (cherry picked from commit 35c637f2e6c671acf8fb9c2a67774bd5e74dd7d0)

commit 24bc377a0ec8fc23df22b396b6b30e6b60b39fb7
Author: Jeremy Allison <jra at samba.org>
Date:   Tue Sep 20 12:08:29 2022 -0700

    s4: smbtorture: Add fsync_resource_fork test to fruit tests.
    
    This shows we currently hang when sending an SMB2_OP_FLUSH on
    an AFP_Resource fork.
    
    Adds knownfail.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15182
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Ralph Böhme <slow at samba.org>
    (cherry picked from commit 1b8a8732848169c632af12b7c2b4cd3ee73be244)

commit b3e8e8185fcb740a780867e69e014d7b87e77afe
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Oct 12 14:57:18 2022 +0200

    smbXsrv_client: handle NAME_NOT_FOUND from smb2srv_client_connection_{pass,drop}()
    
    If we get NT_STATUS_OBJECT_NOT_FOUND from smb2srv_client_connection_{pass,drop}()
    we should just keep the connection and overwrite the stale record in
    smbXsrv_client_global.tdb. It's basically a race with serverid_exists()
    and a process that doesn't cleanly teardown.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15200
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    (cherry picked from commit 5d66d5b84f87267243dcd5223210906ce589af91)

commit 0fa03f112f75dbae7f3f63d245928668df57da45
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Oct 12 14:15:53 2022 +0200

    smbXsrv_client: make sure we only wait for smb2srv_client_mc_negprot_filter once and only when needed
    
    This will simplify the following changes...
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15200
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    (cherry picked from commit 8c8d8cf01e01c2726d03fa1c81e0ce9992ee736c)

commit 935f1ec476edd0688a5471d7a7486da5f92c8b3f
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Oct 12 13:54:41 2022 +0200

    smbXsrv_client: call smb2srv_client_connection_{pass,drop}() before dbwrap_watched_watch_send()
    
    dbwrap_watched_watch_send() should typically be the last thing to call
    before the db record is unlocked, as it's not that easy to undo.
    
    In future we want to recover from smb2srv_client_connection_{pass,drop}()
    returning NT_STATUS_OBJECT_NAME_NOT_FOUND and it would add complexity if
    would need to undo dbwrap_watched_watch_send() at that point.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15200
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    (cherry picked from commit 56c597bc2b29dc3e555f737ba189f521d0e31e8c)

commit 68a233322bdba537546cc4c23c9e97122a67fe59
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Oct 12 13:40:26 2022 +0200

    smbXsrv_client: fix a debug message in smbXsrv_client_global_verify_record()
    
    DBG_WARNING() already adds the function name as prefix.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15200
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    (cherry picked from commit acb3d821deaf06faa16f6428682ecdb02babeb98)

commit f806366dd4a5a551a48526594bd25711376f5f04
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Oct 12 13:30:32 2022 +0200

    smbXsrv_client: ignore NAME_NOT_FOUND from smb2srv_client_connection_passed
    
    If we hit a race, when a client disconnects the connection after the initial
    SMB2 Negotiate request, before the connection is completely passed to
    process serving the given client guid, the temporary smbd which accepted the
    new connection may already detected the disconnect and exitted before
    the long term smbd servicing the client guid was able to send the
    MSG_SMBXSRV_CONNECTION_PASSED message.
    
    The result was a log message like this:
    
      smbXsrv_client_connection_pass_loop: smb2srv_client_connection_passed() failed => NT_STATUS_OBJECT_NAME_NOT_FOUND
    
    and all connections belonging to the client guid were dropped,
    because we called exit_server_cleanly().
    
    Now we ignore NT_STATUS_OBJECT_NAME_NOT_FOUND from
    smb2srv_client_connection_passed() and let the normal
    event loop detect the broken connection, so that only
    that connection is terminated (not the whole smbd process).
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15200
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    (cherry picked from commit 636ec45c93ad040ba70296aa543884c145b3e789)

commit 52dd57d4b30218b93231cf1a990c8829b0c06033
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Aug 30 20:45:50 2022 +0200

    smbXsrv_client: notify a different node to drop a connection by client guid.
    
    If a client disconnected all its interfaces and reconnects when
    the come back, it will likely start from any ip address returned
    dns, which means it can try to connect to a different ctdb node.
    The old node may not have noticed the disconnect and still holds
    the client_guid based smbd.
    
    Up unil now the new node returned NT_STATUS_NOT_SUPPORTED to
    the SMB2 Negotiate request, as messaging_send_iov[_from]() will
    return -1/ENOSYS if a file descriptor os passed to a process on
    a different node.
    
    Now we tell the other node to teardown all client connections
    belonging to the client-guid.
    
    Note that this is not authenticated, but if an attacker can
    capture the client-guid, he can also inject TCP resets anyway,
    to get the same effect.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15159
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    
    Autobuild-User(master): Jeremy Allison <jra at samba.org>
    Autobuild-Date(master): Fri Sep  2 20:59:15 UTC 2022 on sn-devel-184
    
    (cherry picked from commit 8591d9424371e173b079d5c8a267ea4c2cb266ad)

commit ada5ef9d847f17fd00fd1704300258de97c69e6f
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Aug 30 16:56:12 2022 +0200

    smbXsrv_client: correctly check in negotiate_request.length smbXsrv_client_connection_pass[ed]_*
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15159
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    (cherry picked from commit 21ef01e7b8368caa050ed82b9d787d1679220b2b)

-----------------------------------------------------------------------

Summary of changes:
 librpc/idl/messaging.idl       |   1 +
 source3/librpc/idl/smbXsrv.idl |  28 ++++
 source3/modules/vfs_fruit.c    | 114 +++++++++++++-
 source3/smbd/smbXsrv_client.c  | 335 +++++++++++++++++++++++++++++++++++++----
 source4/torture/vfs/fruit.c    |  80 ++++++++++
 5 files changed, 530 insertions(+), 28 deletions(-)


Changeset truncated at 500 lines:

diff --git a/librpc/idl/messaging.idl b/librpc/idl/messaging.idl
index d6929c799ad..5d217c03f5b 100644
--- a/librpc/idl/messaging.idl
+++ b/librpc/idl/messaging.idl
@@ -138,6 +138,7 @@ interface messaging
 		MSG_SMBXSRV_SESSION_CLOSE	= 0x0600,
 		MSG_SMBXSRV_CONNECTION_PASS	= 0x0601,
 		MSG_SMBXSRV_CONNECTION_PASSED	= 0x0602,
+		MSG_SMBXSRV_CONNECTION_DROP	= 0x0603,
 
 		/* source4 and NTVFS smb server messages */
 		MSG_BRL_RETRY                   = 0x0700,
diff --git a/source3/librpc/idl/smbXsrv.idl b/source3/librpc/idl/smbXsrv.idl
index fc502009b3b..ec65a5c1a61 100644
--- a/source3/librpc/idl/smbXsrv.idl
+++ b/source3/librpc/idl/smbXsrv.idl
@@ -143,6 +143,7 @@ interface smbXsrv
 		boolean8		server_multi_channel_enabled;
 		hyper			next_channel_id;
 		[ignore] struct tevent_req		*connection_pass_subreq;
+		[ignore] struct tevent_req		*connection_drop_subreq;
 
 		/*
 		 * A List of pending breaks.
@@ -194,6 +195,33 @@ interface smbXsrv
 		[in] smbXsrv_connection_passB blob
 		);
 
+	/*
+	 * smbXsrv_connection_drop is used in the MSG_SMBXSRV_CONNECTION_DROP
+	 * message as reaction the record is deleted.
+	 */
+	typedef struct {
+		GUID					client_guid;
+		server_id				src_server_id;
+		NTTIME					xconn_connect_time;
+		server_id				dst_server_id;
+		NTTIME					client_connect_time;
+	} smbXsrv_connection_drop0;
+
+	typedef union {
+		[case(0)] smbXsrv_connection_drop0	*info0;
+		[default] hyper				*dummy;
+	} smbXsrv_connection_dropU;
+
+	typedef [public] struct {
+		smbXsrv_version_values			version;
+		[value(0)] uint32			reserved;
+		[switch_is(version)] smbXsrv_connection_dropU	info;
+	} smbXsrv_connection_dropB;
+
+	void smbXsrv_connection_drop_decode(
+		[in] smbXsrv_connection_dropB blob
+		);
+
 	/* sessions */
 
 	typedef [public,bitmap8bit] bitmap {
diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c
index 303df41258e..ba210ac6ace 100644
--- a/source3/modules/vfs_fruit.c
+++ b/source3/modules/vfs_fruit.c
@@ -2624,13 +2624,17 @@ static ssize_t fruit_pread_recv(struct tevent_req *req,
 {
 	struct fruit_pread_state *state = tevent_req_data(
 		req, struct fruit_pread_state);
+	ssize_t retval = -1;
 
 	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
+		tevent_req_received(req);
 		return -1;
 	}
 
 	*vfs_aio_state = state->vfs_aio_state;
-	return state->nread;
+	retval = state->nread;
+	tevent_req_received(req);
+	return retval;
 }
 
 static ssize_t fruit_pwrite_meta_stream(vfs_handle_struct *handle,
@@ -3049,13 +3053,117 @@ static ssize_t fruit_pwrite_recv(struct tevent_req *req,
 {
 	struct fruit_pwrite_state *state = tevent_req_data(
 		req, struct fruit_pwrite_state);
+	ssize_t retval = -1;
+
+	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
+		tevent_req_received(req);
+		return -1;
+	}
+
+	*vfs_aio_state = state->vfs_aio_state;
+	retval = state->nwritten;
+	tevent_req_received(req);
+	return retval;
+}
+
+struct fruit_fsync_state {
+	int ret;
+	struct vfs_aio_state vfs_aio_state;
+};
+
+static void fruit_fsync_done(struct tevent_req *subreq);
+
+static struct tevent_req *fruit_fsync_send(
+	struct vfs_handle_struct *handle,
+	TALLOC_CTX *mem_ctx,
+	struct tevent_context *ev,
+	struct files_struct *fsp)
+{
+	struct tevent_req *req = NULL;
+	struct tevent_req *subreq = NULL;
+	struct fruit_fsync_state *state = NULL;
+	struct fio *fio = fruit_get_complete_fio(handle, fsp);
+
+	req = tevent_req_create(mem_ctx, &state,
+				struct fruit_fsync_state);
+	if (req == NULL) {
+		return NULL;
+	}
+
+	if (fruit_must_handle_aio_stream(fio)) {
+		struct adouble *ad = NULL;
+
+		if (fio->type == ADOUBLE_META) {
+			/*
+			 * We must never pass a fake_fd
+			 * to lower level fsync calls.
+			 * Everything is already done
+			 * synchronously, so just return
+			 * true.
+			 */
+			SMB_ASSERT(fio->fake_fd);
+			tevent_req_done(req);
+			return tevent_req_post(req, ev);
+		}
+
+		/*
+		 * We know the following must be true,
+		 * as it's the condition for fruit_must_handle_aio_stream()
+		 * to return true if fio->type == ADOUBLE_RSRC.
+		 */
+		SMB_ASSERT(fio->config->rsrc == FRUIT_RSRC_ADFILE);
+		if (fio->ad_fsp == NULL) {
+			tevent_req_error(req, EBADF);
+			return tevent_req_post(req, ev);
+		}
+		ad = ad_fget(talloc_tos(), handle, fio->ad_fsp, ADOUBLE_RSRC);
+		if (ad == NULL) {
+			tevent_req_error(req, ENOMEM);
+			return tevent_req_post(req, ev);
+		}
+		fsp = fio->ad_fsp;
+	}
+
+	subreq = SMB_VFS_NEXT_FSYNC_SEND(state, ev, handle, fsp);
+	if (tevent_req_nomem(req, subreq)) {
+		return tevent_req_post(req, ev);
+	}
+	tevent_req_set_callback(subreq, fruit_fsync_done, req);
+	return req;
+}
+
+static void fruit_fsync_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	struct fruit_fsync_state *state = tevent_req_data(
+		req, struct fruit_fsync_state);
+
+	state->ret = SMB_VFS_FSYNC_RECV(subreq, &state->vfs_aio_state);
+	TALLOC_FREE(subreq);
+	if (state->ret != 0) {
+		tevent_req_error(req, errno);
+		return;
+	}
+	tevent_req_done(req);
+}
+
+static int fruit_fsync_recv(struct tevent_req *req,
+					struct vfs_aio_state *vfs_aio_state)
+{
+	struct fruit_fsync_state *state = tevent_req_data(
+		req, struct fruit_fsync_state);
+	int retval = -1;
 
 	if (tevent_req_is_unix_error(req, &vfs_aio_state->error)) {
+		tevent_req_received(req);
 		return -1;
 	}
 
 	*vfs_aio_state = state->vfs_aio_state;
-	return state->nwritten;
+	retval = state->ret;
+	tevent_req_received(req);
+	return retval;
 }
 
 /**
@@ -5277,6 +5385,8 @@ static struct vfs_fn_pointers vfs_fruit_fns = {
 	.pread_recv_fn = fruit_pread_recv,
 	.pwrite_send_fn = fruit_pwrite_send,
 	.pwrite_recv_fn = fruit_pwrite_recv,
+	.fsync_send_fn = fruit_fsync_send,
+	.fsync_recv_fn = fruit_fsync_recv,
 	.stat_fn = fruit_stat,
 	.lstat_fn = fruit_lstat,
 	.fstat_fn = fruit_fstat,
diff --git a/source3/smbd/smbXsrv_client.c b/source3/smbd/smbXsrv_client.c
index 277ae1bab25..28e5035d21d 100644
--- a/source3/smbd/smbXsrv_client.c
+++ b/source3/smbd/smbXsrv_client.c
@@ -189,6 +189,7 @@ static void smbXsrv_client_global_verify_record(struct db_record *db_rec,
 					bool *is_free,
 					bool *was_free,
 					TALLOC_CTX *mem_ctx,
+					const struct server_id *dead_server_id,
 					struct smbXsrv_client_global0 **_g)
 {
 	TDB_DATA key;
@@ -197,6 +198,7 @@ static void smbXsrv_client_global_verify_record(struct db_record *db_rec,
 	struct smbXsrv_client_globalB global_blob;
 	enum ndr_err_code ndr_err;
 	struct smbXsrv_client_global0 *global = NULL;
+	bool dead = false;
 	bool exists;
 	TALLOC_CTX *frame = talloc_stackframe();
 
@@ -227,8 +229,7 @@ static void smbXsrv_client_global_verify_record(struct db_record *db_rec,
 			(ndr_pull_flags_fn_t)ndr_pull_smbXsrv_client_globalB);
 	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 		NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
-		DBG_WARNING("smbXsrv_client_global_verify_record: "
-			    "key '%s' ndr_pull_struct_blob - %s\n",
+		DBG_WARNING("key '%s' ndr_pull_struct_blob - %s\n",
 			    hex_encode_talloc(frame, key.dptr, key.dsize),
 			    nt_errstr(status));
 		TALLOC_FREE(frame);
@@ -251,6 +252,22 @@ static void smbXsrv_client_global_verify_record(struct db_record *db_rec,
 
 	global = global_blob.info.info0;
 
+	dead = server_id_equal(dead_server_id, &global->server_id);
+	if (dead) {
+		struct server_id_buf tmp;
+
+		DBG_NOTICE("key '%s' server_id %s is already dead.\n",
+			   hex_encode_talloc(frame, key.dptr, key.dsize),
+			   server_id_str_buf(global->server_id, &tmp));
+		if (DEBUGLVL(DBGLVL_NOTICE)) {
+			NDR_PRINT_DEBUG(smbXsrv_client_globalB, &global_blob);
+		}
+		TALLOC_FREE(frame);
+		dbwrap_record_delete(db_rec);
+		*is_free = true;
+		return;
+	}
+
 	exists = serverid_exists(&global->server_id);
 	if (!exists) {
 		struct server_id_buf tmp;
@@ -339,6 +356,55 @@ static NTSTATUS smb2srv_client_connection_pass(struct smbd_smb2_request *smb2req
 	return NT_STATUS_OK;
 }
 
+static NTSTATUS smb2srv_client_connection_drop(struct smbd_smb2_request *smb2req,
+					       struct smbXsrv_client_global0 *global)
+{
+	DATA_BLOB blob;
+	enum ndr_err_code ndr_err;
+	NTSTATUS status;
+	struct smbXsrv_connection_drop0 drop_info0;
+	struct smbXsrv_connection_dropB drop_blob;
+	struct iovec iov;
+
+	drop_info0 = (struct smbXsrv_connection_drop0) {
+		.client_guid = global->client_guid,
+		.src_server_id = smb2req->xconn->client->global->server_id,
+		.xconn_connect_time = smb2req->xconn->client->global->initial_connect_time,
+		.dst_server_id = global->server_id,
+		.client_connect_time = global->initial_connect_time,
+	};
+
+	ZERO_STRUCT(drop_blob);
+	drop_blob.version = smbXsrv_version_global_current();
+	drop_blob.info.info0 = &drop_info0;
+
+	if (DEBUGLVL(DBGLVL_DEBUG)) {
+		NDR_PRINT_DEBUG(smbXsrv_connection_dropB, &drop_blob);
+	}
+
+	ndr_err = ndr_push_struct_blob(&blob, talloc_tos(), &drop_blob,
+			(ndr_push_flags_fn_t)ndr_push_smbXsrv_connection_dropB);
+	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+		status = ndr_map_error2ntstatus(ndr_err);
+		return status;
+	}
+
+	iov.iov_base = blob.data;
+	iov.iov_len = blob.length;
+
+	status = messaging_send_iov(smb2req->xconn->client->msg_ctx,
+				    global->server_id,
+				    MSG_SMBXSRV_CONNECTION_DROP,
+				    &iov, 1,
+				    NULL, 0);
+	data_blob_free(&blob);
+	if (!NT_STATUS_IS_OK(status)) {
+		return status;
+	}
+
+	return NT_STATUS_OK;
+}
+
 static NTSTATUS smbXsrv_client_global_store(struct smbXsrv_client_global0 *global)
 {
 	struct smbXsrv_client_globalB global_blob;
@@ -414,6 +480,7 @@ struct smb2srv_client_mc_negprot_state {
 	struct tevent_context *ev;
 	struct smbd_smb2_request *smb2req;
 	struct db_record *db_rec;
+	struct tevent_req *filter_subreq;
 };
 
 static void smb2srv_client_mc_negprot_cleanup(struct tevent_req *req,
@@ -470,7 +537,9 @@ static void smb2srv_client_mc_negprot_next(struct tevent_req *req)
 	bool is_free = false;
 	struct tevent_req *subreq = NULL;
 	NTSTATUS status;
+	struct server_id last_server_id = { .pid = 0, };
 
+	TALLOC_FREE(state->filter_subreq);
 	SMB_ASSERT(state->db_rec == NULL);
 	state->db_rec = smbXsrv_client_global_fetch_locked(table->global.db_ctx,
 							   &client_guid,
@@ -480,10 +549,14 @@ static void smb2srv_client_mc_negprot_next(struct tevent_req *req)
 		return;
 	}
 
+verify_again:
+	TALLOC_FREE(global);
+
 	smbXsrv_client_global_verify_record(state->db_rec,
 					    &is_free,
 					    NULL,
 					    state,
+					    &last_server_id,
 					    &global);
 	if (is_free) {
 		/*
@@ -532,15 +605,58 @@ static void smb2srv_client_mc_negprot_next(struct tevent_req *req)
 		return;
 	}
 
-	subreq = messaging_filtered_read_send(state,
-					      state->ev,
-					      client->msg_ctx,
-					      smb2srv_client_mc_negprot_filter,
-					      NULL);
-	if (tevent_req_nomem(subreq, req)) {
-		return;
+	/*
+	 * If last_server_id is set, we expect
+	 * smbXsrv_client_global_verify_record()
+	 * to detect the already dead global->server_id
+	 * as state->db_rec is still locked and its
+	 * value didn't change.
+	 */
+	SMB_ASSERT(last_server_id.pid == 0);
+	last_server_id = global->server_id;
+
+	if (procid_is_local(&global->server_id)) {
+		subreq = messaging_filtered_read_send(state,
+						      state->ev,
+						      client->msg_ctx,
+						      smb2srv_client_mc_negprot_filter,
+						      NULL);
+		if (tevent_req_nomem(subreq, req)) {
+			return;
+		}
+		tevent_req_set_callback(subreq, smb2srv_client_mc_negprot_done, req);
+		state->filter_subreq = subreq;
+	}
+
+	if (procid_is_local(&global->server_id)) {
+		status = smb2srv_client_connection_pass(state->smb2req,
+							global);
+		if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+			/*
+			 * We remembered last_server_id = global->server_id
+			 * above, so we'll treat it as dead in the
+			 * next round to smbXsrv_client_global_verify_record().
+			 */
+			goto verify_again;
+		}
+		if (tevent_req_nterror(req, status)) {
+			return;
+		}
+	} else {
+		status = smb2srv_client_connection_drop(state->smb2req,
+							global);
+		if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+			/*
+			 * We remembered last_server_id = global->server_id
+			 * above, so we'll treat it as dead in the
+			 * next round to smbXsrv_client_global_verify_record().
+			 */
+			goto verify_again;
+		}
+		if (tevent_req_nterror(req, status)) {
+			return;
+		}
 	}
-	tevent_req_set_callback(subreq, smb2srv_client_mc_negprot_done, req);
 
 	subreq = dbwrap_watched_watch_send(state,
 					   state->ev,
@@ -551,13 +667,7 @@ static void smb2srv_client_mc_negprot_next(struct tevent_req *req)
 	}
 	tevent_req_set_callback(subreq, smb2srv_client_mc_negprot_watched, req);
 
-	status = smb2srv_client_connection_pass(state->smb2req,
-						global);
 	TALLOC_FREE(global);
-	if (tevent_req_nterror(req, status)) {
-		return;
-	}
-
 	TALLOC_FREE(state->db_rec);
 	return;
 }
@@ -572,10 +682,6 @@ static bool smb2srv_client_mc_negprot_filter(struct messaging_rec *rec, void *pr
 		return false;
 	}
 
-	if (rec->buf.length < SMB2_HDR_BODY) {
-		return false;
-	}
-
 	return true;
 }
 
@@ -596,6 +702,9 @@ static void smb2srv_client_mc_negprot_done(struct tevent_req *subreq)
 	NTSTATUS status;
 	int ret;
 
+	SMB_ASSERT(state->filter_subreq == subreq);
+	state->filter_subreq = NULL;
+
 	ret = messaging_filtered_read_recv(subreq, state, &rec);
 	TALLOC_FREE(subreq);
 	if (ret != 0) {
@@ -665,6 +774,14 @@ static void smb2srv_client_mc_negprot_done(struct tevent_req *subreq)
 		return;
 	}
 
+	if (passed_info0->negotiate_request.length != 0) {
+		DBG_ERR("negotiate_request.length[%zu]\n",
+			passed_info0->negotiate_request.length);
+		NDR_PRINT_DEBUG(smbXsrv_connection_passB, &passed_blob);
+		tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
+		return;
+	}
+
 	tevent_req_nterror(req, NT_STATUS_MESSAGE_RETRIEVED);
 }
 
@@ -740,6 +857,8 @@ static int smbXsrv_client_destructor(struct smbXsrv_client *client)
 
 static bool smbXsrv_client_connection_pass_filter(struct messaging_rec *rec, void *private_data);
 static void smbXsrv_client_connection_pass_loop(struct tevent_req *subreq);
+static bool smbXsrv_client_connection_drop_filter(struct messaging_rec *rec, void *private_data);
+static void smbXsrv_client_connection_drop_loop(struct tevent_req *subreq);
 
 NTSTATUS smbXsrv_client_create(TALLOC_CTX *mem_ctx,
 			       struct tevent_context *ev_ctx,
@@ -822,6 +941,18 @@ NTSTATUS smbXsrv_client_create(TALLOC_CTX *mem_ctx,
 	tevent_req_set_callback(subreq, smbXsrv_client_connection_pass_loop, client);
 	client->connection_pass_subreq = subreq;
 
+	subreq = messaging_filtered_read_send(client,
+					client->raw_ev_ctx,
+					client->msg_ctx,
+					smbXsrv_client_connection_drop_filter,
+					client);
+	if (subreq == NULL) {
+		TALLOC_FREE(client);
+		return NT_STATUS_NO_MEMORY;
+	}
+	tevent_req_set_callback(subreq, smbXsrv_client_connection_drop_loop, client);
+	client->connection_drop_subreq = subreq;
+
 	*_client = client;
 	return NT_STATUS_OK;
 }
@@ -883,12 +1014,6 @@ static bool smbXsrv_client_connection_pass_filter(struct messaging_rec *rec, voi
 		return false;
 	}
 


-- 
Samba Shared Repository



More information about the samba-cvs mailing list