s3:smbd: try to make fsp->fh->gen_id as globally unique as possible
[ddiss/samba.git] / source3 / smbd / files.c
index f01da2c8a21aac4486e547deb2b4b440881f4bc9..0018ceed5e51cf0b45afa3606b5a78c9146704c6 100644 (file)
 */
 
 #include "includes.h"
+#include "smbd/smbd.h"
 #include "smbd/globals.h"
 #include "libcli/security/security.h"
+#include "util_tdb.h"
 
 #define VALID_FNUM(fnum)   (((fnum) >= 0) && ((fnum) < real_max_open_files))
 
 #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.
+ See bug #8995 for the details.
 ****************************************************************************/
 
 static unsigned long get_gen_count(struct smbd_server_connection *sconn)
 {
+       /*
+        * While fsp->fh->gen_id is 'unsigned long' currently
+        * (which might by 8 bytes),
+        * there's some oplock code which truncates it to
+        * uint32_t(using IVAL()).
+        */
+       if (sconn->file_gen_counter == 0) {
+               sconn->file_gen_counter = generate_random();
+       }
        sconn->file_gen_counter += 1;
+       if (sconn->file_gen_counter >= UINT32_MAX) {
+               sconn->file_gen_counter = 0;
+       }
        if (sconn->file_gen_counter == 0) {
                sconn->file_gen_counter += 1;
        }
@@ -282,6 +298,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) &&
@@ -546,6 +566,49 @@ files_struct *file_fsp(struct smb_request *req, uint16 fid)
        return fsp;
 }
 
+struct files_struct *file_fsp_smb2(struct smbd_smb2_request *smb2req,
+                                  uint64_t persistent_id,
+                                  uint64_t volatile_id)
+{
+       struct files_struct *fsp;
+
+       if (smb2req->compat_chain_fsp != NULL) {
+               return smb2req->compat_chain_fsp;
+       }
+
+       if (persistent_id != volatile_id) {
+               return NULL;
+       }
+
+       if (volatile_id > UINT16_MAX) {
+               return NULL;
+       }
+
+       fsp = file_fnum(smb2req->sconn, (uint16_t)volatile_id);
+       if (fsp == NULL) {
+               return NULL;
+       }
+
+       if (smb2req->tcon == NULL) {
+               return NULL;
+       }
+
+       if (smb2req->tcon->compat_conn != fsp->conn) {
+               return NULL;
+       }
+
+       if (smb2req->session == NULL) {
+               return NULL;
+       }
+
+       if (smb2req->session->vuid != fsp->vuid) {
+               return NULL;
+       }
+
+       smb2req->compat_chain_fsp = fsp;
+       return fsp;
+}
+
 /****************************************************************************
  Duplicate the file handle part for a DOS or FCB open.
 ****************************************************************************/