From: Stefan Metzmacher Date: Fri, 4 Oct 2019 08:02:56 +0000 (+0200) Subject: smb2_server: make sure we detect stale smbXsrv_connection pointers in smbXsrv_channel... X-Git-Tag: ldb-2.2.0~478 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0cec96526bf4d3209caf36c4a19632ff5d5dd112;p=thirdparty%2Fsamba.git smb2_server: make sure we detect stale smbXsrv_connection pointers in smbXsrv_channel_global Pointer values can be reused (yes, I hit that during my testing!). Introduce a channel_id to identify connections and also add some timestamps to make debugging easier. This makes smbXsrv_session_find_channel() much more robust. Signed-off-by: Stefan Metzmacher Reviewed-by: Guenther Deschner --- diff --git a/source3/librpc/idl/smbXsrv.idl b/source3/librpc/idl/smbXsrv.idl index 4d9249fb3bb..bdab9345342 100644 --- a/source3/librpc/idl/smbXsrv.idl +++ b/source3/librpc/idl/smbXsrv.idl @@ -141,6 +141,7 @@ interface smbXsrv */ [ignore] struct smbXsrv_connection *connections; boolean8 server_multi_channel_enabled; + hyper next_channel_id; } smbXsrv_client; typedef union { @@ -200,6 +201,8 @@ interface smbXsrv typedef struct { server_id server_id; + hyper channel_id; + NTTIME creation_time; [charset(UTF8),string] char local_address[]; [charset(UTF8),string] char remote_address[]; [charset(UTF8),string] char remote_name[]; diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 79086b3c81c..77911f051df 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -231,7 +231,7 @@ bool smbd_is_smb2_header(const uint8_t *inbuf, size_t size); bool smbd_smb2_is_compound(const struct smbd_smb2_request *req); NTSTATUS smbd_add_connection(struct smbXsrv_client *client, int sock_fd, - struct smbXsrv_connection **_xconn); + NTTIME now, struct smbXsrv_connection **_xconn); NTSTATUS reply_smb2002(struct smb_request *req, uint16_t choice); NTSTATUS reply_smb20ff(struct smb_request *req, uint16_t choice); @@ -347,6 +347,8 @@ struct smbXsrv_connection { struct smbXsrv_client *client; + NTTIME connect_time; + uint64_t channel_id; const struct tsocket_address *local_address; const struct tsocket_address *remote_address; const char *remote_hostname; @@ -547,6 +549,7 @@ NTSTATUS smbXsrv_session_create(struct smbXsrv_connection *conn, struct smbXsrv_session **_session); NTSTATUS smbXsrv_session_add_channel(struct smbXsrv_session *session, struct smbXsrv_connection *conn, + NTTIME now, struct smbXsrv_channel_global0 **_c); NTSTATUS smbXsrv_session_update(struct smbXsrv_session *session); struct smbXsrv_channel_global0; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 2ea721f24c0..161672bd516 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -3720,7 +3720,7 @@ const char *smbXsrv_connection_dbg(const struct smbXsrv_connection *xconn) } NTSTATUS smbd_add_connection(struct smbXsrv_client *client, int sock_fd, - struct smbXsrv_connection **_xconn) + NTTIME now, struct smbXsrv_connection **_xconn) { TALLOC_CTX *frame = talloc_stackframe(); struct smbXsrv_connection *xconn; @@ -3750,6 +3750,10 @@ NTSTATUS smbd_add_connection(struct smbXsrv_client *client, int sock_fd, return NT_STATUS_NO_MEMORY; } talloc_steal(frame, xconn); + xconn->connect_time = now; + if (client->next_channel_id != 0) { + xconn->channel_id = client->next_channel_id++; + } xconn->transport.sock = sock_fd; smbd_echo_init(xconn); @@ -3994,7 +3998,7 @@ void smbd_process(struct tevent_context *ev_ctx, smbd_setup_sig_hup_handler(sconn); } - status = smbd_add_connection(client, sock_fd, &xconn); + status = smbd_add_connection(client, sock_fd, now, &xconn); if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_ACCESS_DENIED)) { /* * send a negative session response "not listening on calling diff --git a/source3/smbd/smb2_sesssetup.c b/source3/smbd/smb2_sesssetup.c index 3fa1a15910e..f9c8819327c 100644 --- a/source3/smbd/smb2_sesssetup.c +++ b/source3/smbd/smb2_sesssetup.c @@ -912,6 +912,7 @@ static struct tevent_req *smbd_smb2_session_setup_send(TALLOC_CTX *mem_ctx, status = smbXsrv_session_add_channel(smb2req->session, smb2req->xconn, + now, &c); if (!NT_STATUS_IS_OK(status)) { tevent_req_nterror(req, status); diff --git a/source3/smbd/smbXsrv_client.c b/source3/smbd/smbXsrv_client.c index ec5b5f1d04c..c6114d4b8dc 100644 --- a/source3/smbd/smbXsrv_client.c +++ b/source3/smbd/smbXsrv_client.c @@ -523,7 +523,9 @@ NTSTATUS smbXsrv_client_create(TALLOC_CTX *mem_ctx, client->msg_ctx = msg_ctx; client->server_multi_channel_enabled = lp_server_multi_channel_support(); - + if (client->server_multi_channel_enabled) { + client->next_channel_id = 1; + } client->table = talloc_move(client, &table); table = client->table; @@ -673,7 +675,10 @@ static void smbXsrv_client_connection_pass_loop(struct tevent_req *subreq) DBG_ERR("got connection sockfd[%d]\n", sock_fd); NDR_PRINT_DEBUG(smbXsrv_connection_passB, &pass_blob); - status = smbd_add_connection(client, sock_fd, &xconn); + status = smbd_add_connection(client, + sock_fd, + pass_info0->initial_connect_time, + &xconn); if (!NT_STATUS_IS_OK(status)) { close(sock_fd); sock_fd = -1; diff --git a/source3/smbd/smbXsrv_session.c b/source3/smbd/smbXsrv_session.c index 7d63efb758f..1ebed144afd 100644 --- a/source3/smbd/smbXsrv_session.c +++ b/source3/smbd/smbXsrv_session.c @@ -1293,7 +1293,7 @@ NTSTATUS smbXsrv_session_create(struct smbXsrv_connection *conn, global->creation_time = now; global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY; - status = smbXsrv_session_add_channel(session, conn, &channel); + status = smbXsrv_session_add_channel(session, conn, now, &channel); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(session); return status; @@ -1338,6 +1338,7 @@ NTSTATUS smbXsrv_session_create(struct smbXsrv_connection *conn, NTSTATUS smbXsrv_session_add_channel(struct smbXsrv_session *session, struct smbXsrv_connection *conn, + NTTIME now, struct smbXsrv_channel_global0 **_c) { struct smbXsrv_session_global0 *global = session->global; @@ -1363,6 +1364,8 @@ NTSTATUS smbXsrv_session_add_channel(struct smbXsrv_session *session, ZERO_STRUCTP(c); c->server_id = messaging_server_id(conn->client->msg_ctx); + c->channel_id = conn->channel_id; + c->creation_time = now; c->local_address = tsocket_address_string(conn->local_address, global->channels); if (c->local_address == NULL) { @@ -1438,10 +1441,16 @@ NTSTATUS smbXsrv_session_find_channel(const struct smbXsrv_session *session, for (i=0; i < session->global->num_channels; i++) { struct smbXsrv_channel_global0 *c = &session->global->channels[i]; - if (c->connection == conn) { - *_c = c; - return NT_STATUS_OK; + if (c->channel_id != conn->channel_id) { + continue; + } + + if (c->connection != conn) { + continue; } + + *_c = c; + return NT_STATUS_OK; } return NT_STATUS_USER_SESSION_DELETED;