From d122f7a71e35b4b1774a3afcfeb951d1c9060600 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 13 Jun 2012 16:07:20 -0700 Subject: [PATCH 1/3] Part 1 of fix for bug #8995 - SMB2 - Persistent File IDs must be unique. Based on code from Ira Cooper. Ensure fsp->fh->gen_id starts from a random point. We will use this as the SMB2 persistent_id. --- source3/smbd/files.c | 15 ++++++++++++++- 1 files changed, 14 insertions(+), 1 deletions(-) diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 97db348..e97c3e6 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -28,12 +28,21 @@ #define FILE_HANDLE_OFFSET 0x1000 /**************************************************************************** - Return a unique number identifying this fsp over the life of this pid. + Return a unique number identifying this fsp over the life of this pid, + and try to make it as globally unique as possible. We do this as we will + use fsp->fh->gen_id as the persistent_id for SMB2 opens. ****************************************************************************/ static unsigned long get_gen_count(struct smbd_server_connection *sconn) { + if (sconn->file_gen_counter == 0) { + generate_random_buffer((uint8_t *)&sconn->file_gen_counter, + sizeof(sconn->file_gen_counter)); + } sconn->file_gen_counter += 1; + if (sconn->file_gen_counter == UINT64_MAX) { + sconn->file_gen_counter = 0; + } if (sconn->file_gen_counter == 0) { sconn->file_gen_counter += 1; } @@ -315,6 +324,10 @@ files_struct *file_find_dif(struct smbd_server_connection *sconn, int count=0; files_struct *fsp; + if (gen_id == 0) { + return NULL; + } + for (fsp=sconn->files; fsp; fsp=fsp->next,count++) { /* We can have a fsp->fh->fd == -1 here as it could be a stat open. */ if (file_id_equal(&fsp->file_id, &id) && -- 1.7.7.3 From f1e06f5ad04d3042094351c35f39b8a7f3759c48 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 13 Jun 2012 16:14:16 -0700 Subject: [PATCH 2/3] Part 2 of fix for bug #8995 - SMB2 - Persistent File IDs must be unique. Based on code from Ira Cooper. Use fsp->fh->gen_id as the persistent fileid in SMB2. --- source3/smbd/files.c | 8 ++++---- source3/smbd/smb2_break.c | 2 +- source3/smbd/smb2_create.c | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/source3/smbd/files.c b/source3/smbd/files.c index e97c3e6..d2a8ac8 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -601,10 +601,6 @@ struct files_struct *file_fsp_smb2(struct smbd_smb2_request *smb2req, return smb2req->compat_chain_fsp; } - if (persistent_id != volatile_id) { - return NULL; - } - if (volatile_id > UINT16_MAX) { return NULL; } @@ -614,6 +610,10 @@ struct files_struct *file_fsp_smb2(struct smbd_smb2_request *smb2req, return NULL; } + if (persistent_id != (uint64_t)fsp->fh->gen_id) { + return NULL; + } + if (smb2req->tcon == NULL) { return NULL; } diff --git a/source3/smbd/smb2_break.c b/source3/smbd/smb2_break.c index 75505e5..93f5ca3 100644 --- a/source3/smbd/smb2_break.c +++ b/source3/smbd/smb2_break.c @@ -245,7 +245,7 @@ void send_break_message_smb2(files_struct *fsp, int level) (unsigned int)smb2_oplock_level )); status = smbd_smb2_send_oplock_break(fsp->conn->sconn, - (uint64_t)fsp->fnum, + (uint64_t)fsp->fh->gen_id, (uint64_t)fsp->fnum, smb2_oplock_level); if (!NT_STATUS_IS_OK(status)) { diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c index 2aedfb6..b3b366e 100644 --- a/source3/smbd/smb2_create.c +++ b/source3/smbd/smb2_create.c @@ -822,7 +822,7 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, if (state->out_file_attributes == 0) { state->out_file_attributes = FILE_ATTRIBUTE_NORMAL; } - state->out_file_id_persistent = result->fnum; + state->out_file_id_persistent = result->fh->gen_id; state->out_file_id_volatile = result->fnum; state->out_context_blobs = out_context_blobs; -- 1.7.7.3 From c00a258de16b0cebc3668e8dd64926ae3b53c917 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 13 Jun 2012 16:15:35 -0700 Subject: [PATCH 3/3] Part 3 of fix for bug #8995 - SMB2 - Persistent File IDs must be unique. Only set fsp->fh->gen for a client connection. For faked connections, like dfs and printing, we leave it as 0. --- source3/smbd/files.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/source3/smbd/files.c b/source3/smbd/files.c index d2a8ac8..d6c42a2 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -114,7 +114,6 @@ NTSTATUS file_new(struct smb_request *req, connection_struct *conn, fsp->fnum = -1; fsp->conn = conn; - fsp->fh->gen_id = get_gen_count(sconn); GetTimeOfDay(&fsp->open_time); if (sconn->file_bmap != NULL) { @@ -124,6 +123,8 @@ NTSTATUS file_new(struct smb_request *req, connection_struct *conn, fsp->fnum = i + FILE_HANDLE_OFFSET; SMB_ASSERT(fsp->fnum < 65536); + + fsp->fh->gen_id = get_gen_count(sconn); } DLIST_ADD(sconn->files, fsp); -- 1.7.7.3