local.h: Fix spelling mistake :-).
[kai/samba.git] / source3 / smbd / trans2.c
index 1f727c4ecdf7907c0ba7c8baeb10322ccc4aa29d..092a069a6e33b4a66d7d5fe24c3c453466df293c 100644 (file)
@@ -166,7 +166,7 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum,
   char *params = *pparams;
   int16 open_mode = SVAL(params, 2);
   int16 open_attr = SVAL(params,6);
-  BOOL oplock_request = BITSETW(params,1);
+  BOOL oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
 #if 0
   BOOL return_additional_info = BITSETW(params,0);
   int16 open_sattr = SVAL(params, 4);
@@ -184,6 +184,7 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum,
   int32 inode = 0;
   struct stat sbuf;
   int smb_action = 0;
+  BOOL bad_path = False;
 
   StrnCpy(fname,pname,namelen);
 
@@ -192,23 +193,37 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum,
 
   /* XXXX we need to handle passed times, sattr and flags */
 
-  unix_convert(fname,cnum,0);
+  unix_convert(fname,cnum,0,&bad_path);
     
   fnum = find_free_file();
   if (fnum < 0)
     return(ERROR(ERRSRV,ERRnofids));
 
   if (!check_name(fname,cnum))
+  {
+    if((errno == ENOENT) && bad_path)
+    {
+      unix_ERR_class = ERRDOS;
+      unix_ERR_code = ERRbadpath;
+    }
     return(UNIXERROR(ERRDOS,ERRnoaccess));
+  }
 
   unixmode = unix_mode(cnum,open_attr | aARCH);
       
       
   open_file_shared(fnum,cnum,fname,open_mode,open_ofun,unixmode,
-                  &rmode,&smb_action);
+                  oplock_request, &rmode,&smb_action);
       
   if (!Files[fnum].open)
+  {
+    if((errno == ENOENT) && bad_path)
+    {
+      unix_ERR_class = ERRDOS;
+      unix_ERR_code = ERRbadpath;
+    }
     return(UNIXERROR(ERRDOS,ERRnoaccess));
+  }
 
   if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
     close_file(fnum);
@@ -237,7 +252,7 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum,
   SSVAL(params,12,rmode);
 
   if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
-    smb_action |= (1<<15);
+    smb_action |= EXTENDED_OPLOCK_GRANTED;
   }
 
   SSVAL(params,18,smb_action);
@@ -291,10 +306,10 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l
       if(p[1] == '\0')
        strcpy(mask,"*.*");
       else
-       strcpy(mask, p+1);
+       pstrcpy(mask, p+1);
     }
   else
-    strcpy(mask, path_mask);
+    pstrcpy(mask, path_mask);
 
   while (!found)
     {
@@ -304,7 +319,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l
 
       reskey = TellDir(Connections[cnum].dirptr);
 
-      DEBUG(6,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n",
+      DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n",
               Connections[cnum].dirptr,TellDir(Connections[cnum].dirptr)));
       
       if (!dname) 
@@ -312,7 +327,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l
 
       matched = False;
 
-      strcpy(fname,dname);      
+      pstrcpy(fname,dname);      
 
       if(mask_match(fname, mask, case_sensitive, True))
        {
@@ -323,10 +338,10 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l
          if (isrootdir && isdots)
            continue;
 
-         strcpy(pathreal,Connections[cnum].dirpath);
+         pstrcpy(pathreal,Connections[cnum].dirpath);
           if(needslash)
            strcat(pathreal,"/");
-         strcat(pathreal,fname);
+         strcat(pathreal,dname);
          if (sys_stat(pathreal,&sbuf) != 0) 
            {
              DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",pathreal,strerror(errno)));
@@ -353,13 +368,11 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l
        }
     }
 
-
+  name_map_mangle(fname,False,SNUM(cnum));
 
   p = pdata;
   nameptr = p;
 
-  name_map_mangle(fname,False,SNUM(cnum));
-
   nt_extmode = mode ? mode : NT_FILE_ATTRIBUTE_NORMAL;
 
   switch (info_level)
@@ -559,6 +572,7 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum
   BOOL dont_descend = False;
   BOOL out_of_space = False;
   int space_remaining;
+  BOOL bad_path = False;
 
   *directory = *mask = 0;
 
@@ -581,13 +595,29 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum
       return(ERROR(ERRDOS,ERRunknownlevel));
     }
 
-  strcpy(directory, params + 12); /* Complete directory path with 
+  pstrcpy(directory, params + 12); /* Complete directory path with 
                                     wildcard mask appended */
 
   DEBUG(5,("path=%s\n",directory));
 
-  unix_convert(directory,cnum,0);
+  unix_convert(directory,cnum,0,&bad_path);
   if(!check_name(directory,cnum)) {
+    if((errno == ENOENT) && bad_path)
+    {
+      unix_ERR_class = ERRDOS;
+      unix_ERR_code = ERRbadpath;
+    }
+
+#if 0
+    /* Ugly - NT specific hack - maybe not needed ? (JRA) */
+    if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && 
+       (get_remote_arch() == RA_WINNT))
+    {
+      unix_ERR_class = ERRDOS;
+      unix_ERR_code = ERRbaddirectory;
+    }
+#endif 
+
     return(ERROR(ERRDOS,ERRbadpath));
   }
 
@@ -614,7 +644,29 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum
 
   dptr_num = dptr_create(cnum,directory, True ,SVAL(inbuf,smb_pid));
   if (dptr_num < 0)
-    return(ERROR(ERRDOS,ERRbadpath));
+    {
+      if(dptr_num == -2)
+      {
+        if((errno == ENOENT) && bad_path)
+        {
+          unix_ERR_class = ERRDOS;
+          unix_ERR_code = ERRbadpath;
+        }
+
+#if 0
+        /* Ugly - NT specific hack - maybe not needed ? (JRA) */
+        if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) && 
+           (get_remote_arch() == RA_WINNT))
+        {
+          unix_ERR_class = ERRDOS;
+          unix_ERR_code = ERRbaddirectory;
+        }
+#endif
+
+        return (UNIXERROR(ERRDOS,ERRbadpath));
+      }
+      return(ERROR(ERRDOS,ERRbadpath));
+    }
 
   /* convert the formatted masks */
   {
@@ -918,7 +970,7 @@ static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize
       put_dos_date2(pdata,l2_vol_fdateCreation,st.st_ctime);
       SCVAL(pdata,l2_vol_cch,volname_len);
       StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len);
-      DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",st.st_ctime,volname_len,
+      DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",st.st_ctime, volname_len,
               pdata+l2_vol_szVolLabel));
       break;
     }
@@ -1008,7 +1060,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length,
   char *fname;
   char *p;
   int l,pos;
-
+  BOOL bad_path = False;
 
   if (tran_call == TRANSACT2_QFILEINFO) {
     int16 fnum = SVALS(params,0);
@@ -1027,10 +1079,15 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length,
     /* qpathinfo */
     info_level = SVAL(params,0);
     fname = &fname1[0];
-    strcpy(fname,&params[6]);
-    unix_convert(fname,cnum,0);
+    pstrcpy(fname,&params[6]);
+    unix_convert(fname,cnum,0,&bad_path);
     if (!check_name(fname,cnum) || sys_stat(fname,&sbuf)) {
       DEBUG(3,("fileinfo of %s failed (%s)\n",fname,strerror(errno)));
+      if((errno == ENOENT) && bad_path)
+      {
+        unix_ERR_class = ERRDOS;
+        unix_ERR_code = ERRbadpath;
+      }
       return(UNIXERROR(ERRDOS,ERRbadpath));
     }
     pos = 0;
@@ -1057,34 +1114,28 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length,
   if (total_data > 0 && IVAL(pdata,0) == total_data) {
     /* uggh, EAs for OS2 */
     DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
-#if 0
-    SSVAL(params,0,ERROR_EAS_NOT_SUPPORTED);
-    send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
-    return(-1);
-#else
     return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
-#endif
   }
 
   bzero(pdata,data_size);
 
   switch (info_level) 
     {
-    case 1:
-    case 2:
+    case SMB_INFO_STANDARD:
+    case SMB_INFO_QUERY_EA_SIZE:
       data_size = (info_level==1?22:26);
-      put_dos_date2(pdata,l1_fdateCreation,sbuf.st_ctime);
-      put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
-      put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime);
+      put_dos_date2(pdata,l1_fdateCreation,sbuf.st_ctime); /* create = inode mod */
+      put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); /* access time */
+      put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
       SIVAL(pdata,l1_cbFile,size);
       SIVAL(pdata,l1_cbFileAlloc,ROUNDUP(size,1024));
       SSVAL(pdata,l1_attrFile,mode);
       SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
       break;
 
-    case 3:
+    case SMB_INFO_QUERY_EAS_FROM_LIST:
       data_size = 24;
-      put_dos_date2(pdata,0,sbuf.st_ctime);
+      put_dos_date2(pdata,0,sbuf.st_ctime); /* create time = inode mod time */
       put_dos_date2(pdata,4,sbuf.st_atime);
       put_dos_date2(pdata,8,sbuf.st_mtime);
       SIVAL(pdata,12,size);
@@ -1092,7 +1143,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length,
       SIVAL(pdata,20,mode);
       break;
 
-    case 4:
+    case SMB_INFO_QUERY_ALL_EAS:
       data_size = 4;
       SIVAL(pdata,0,data_size);
       break;
@@ -1101,12 +1152,20 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length,
       return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */      
 
     case SMB_QUERY_FILE_BASIC_INFO:
-      data_size = 36;
-      put_long_date(pdata,sbuf.st_ctime);
-      put_long_date(pdata+8,sbuf.st_atime);
-      put_long_date(pdata+16,sbuf.st_mtime);
-      put_long_date(pdata+24,sbuf.st_mtime);
+      data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
+      put_long_date(pdata,sbuf.st_ctime); /* create time = inode mod time */
+      put_long_date(pdata+8,sbuf.st_atime); /* access time */
+      put_long_date(pdata+16,sbuf.st_mtime); /* write time */
+      put_long_date(pdata+24,sbuf.st_mtime); /* change time */
       SIVAL(pdata,32,mode);
+
+      DEBUG(5,("SMB_QFBI - "));
+      DEBUG(5,("create: %s ", ctime(&sbuf.st_ctime)));
+      DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
+      DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
+      DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
+      DEBUG(5,("mode: %x\n", mode));
+
       break;
 
     case SMB_QUERY_FILE_STANDARD_INFO:
@@ -1126,7 +1185,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length,
     case SMB_QUERY_FILE_ALT_NAME_INFO:
       data_size = 4 + l;
       SIVAL(pdata,0,l);
-      strcpy(pdata+4,fname);
+      pstrcpy(pdata+4,fname);
       break;
     case SMB_QUERY_FILE_ALLOCATION_INFO:
     case SMB_QUERY_FILE_END_OF_FILEINFO:
@@ -1135,10 +1194,10 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length,
       break;
 
     case SMB_QUERY_FILE_ALL_INFO:
-      put_long_date(pdata,sbuf.st_ctime);
-      put_long_date(pdata+8,sbuf.st_atime);
-      put_long_date(pdata+16,sbuf.st_mtime);
-      put_long_date(pdata+24,sbuf.st_mtime);
+      put_long_date(pdata,sbuf.st_ctime); /* create time = inode mod time */
+      put_long_date(pdata+8,sbuf.st_atime); /* access time */
+      put_long_date(pdata+16,sbuf.st_mtime); /* write time */
+      put_long_date(pdata+24,sbuf.st_mtime); /* change time */
       SIVAL(pdata,32,mode);
       pdata += 40;
       SIVAL(pdata,0,size);
@@ -1160,7 +1219,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length,
       pdata += 4;
       pdata += 4; /* alignment */
       SIVAL(pdata,0,l);
-      strcpy(pdata+4,fname);
+      pstrcpy(pdata+4,fname);
       pdata += 4 + l;
       data_size = PTR_DIFF(pdata,(*ppdata));
       break;
@@ -1171,7 +1230,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length,
       SIVAL(pdata,4,size);
       SIVAL(pdata,12,size);
       SIVAL(pdata,20,l);       
-      strcpy(pdata+24,fname);
+      pstrcpy(pdata+24,fname);
       break;
     default:
       return(ERROR(ERRDOS,ERRunknownlevel));
@@ -1200,6 +1259,7 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length,
   pstring fname1;
   char *fname;
   int fd = -1;
+  BOOL bad_path = False;
 
   if (!CAN_WRITE(cnum))
     return(ERROR(ERRSRV,ERRaccess));
@@ -1222,14 +1282,26 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length,
     /* set path info */
     info_level = SVAL(params,0);    
     fname = fname1;
-    strcpy(fname,&params[6]);
-    unix_convert(fname,cnum,0);
+    pstrcpy(fname,&params[6]);
+    unix_convert(fname,cnum,0,&bad_path);
     if(!check_name(fname, cnum))
-      return(ERROR(ERRDOS,ERRbadpath));
-    
+    {
+      if((errno == ENOENT) && bad_path)
+      {
+        unix_ERR_class = ERRDOS;
+        unix_ERR_code = ERRbadpath;
+      }
+      return(UNIXERROR(ERRDOS,ERRbadpath));
+    }
     if(sys_stat(fname,&st)!=0) {
       DEBUG(3,("stat of %s failed (%s)\n", fname, strerror(errno)));
-      return(ERROR(ERRDOS,ERRbadpath));
+      if((errno == ENOENT) && bad_path)
+      {
+        unix_ERR_class = ERRDOS;
+        unix_ERR_code = ERRbadpath;
+      }
+      return(UNIXERROR(ERRDOS,ERRbadpath));
     }    
   }
 
@@ -1249,37 +1321,37 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length,
   if (total_data > 0 && IVAL(pdata,0) == total_data) {
     /* uggh, EAs for OS2 */
     DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
-    SSVAL(params,0,ERROR_EAS_NOT_SUPPORTED);
-
-    send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
-  
-    return(-1);    
+    return(ERROR(ERRDOS,ERROR_EAS_NOT_SUPPORTED));
   }
 
   switch (info_level)
+  {
+    case SMB_INFO_STANDARD:
+    case SMB_INFO_QUERY_EA_SIZE:
     {
-    case 1:
+      /* access time */
       tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
-      tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
-      mode = SVAL(pdata,l1_attrFile);
-      size = IVAL(pdata,l1_cbFile);
-      break;
 
-    case 2:
-      tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
+      /* write time */
       tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
+
       mode = SVAL(pdata,l1_attrFile);
       size = IVAL(pdata,l1_cbFile);
       break;
+    }
 
-    case 3:
+    /* XXXX um, i don't think this is right.
+       it's also not in the cifs6.txt spec.
+     */
+    case SMB_INFO_QUERY_EAS_FROM_LIST:
       tvs.actime = make_unix_date2(pdata+8);
       tvs.modtime = make_unix_date2(pdata+12);
       size = IVAL(pdata,16);
       mode = IVAL(pdata,24);
       break;
 
-    case 4:
+    /* XXXX nor this.  not in cifs6.txt, either. */
+    case SMB_INFO_QUERY_ALL_EAS:
       tvs.actime = make_unix_date2(pdata+8);
       tvs.modtime = make_unix_date2(pdata+12);
       size = IVAL(pdata,16);
@@ -1287,48 +1359,87 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length,
       break;
 
     case SMB_SET_FILE_BASIC_INFO:
-      pdata += 8;              /* create time */
-      tvs.actime = interpret_long_date(pdata); pdata += 8;
-      tvs.modtime=MAX(interpret_long_date(pdata),interpret_long_date(pdata+8));
-      pdata += 16;
-      mode = IVAL(pdata,0);
+    {
+      /* Ignore create time at offset pdata. */
+
+      /* access time */
+      tvs.actime = interpret_long_date(pdata+8);
+
+      /* write time + changed time, combined. */
+      tvs.modtime=MAX(interpret_long_date(pdata+16),
+                      interpret_long_date(pdata+24));
+
+#if 0 /* Needs more testing... */
+      /* Test from Luke to prevent Win95 from
+         setting incorrect values here.
+       */
+      if (tvs.actime < tvs.modtime)
+        return(ERROR(ERRDOS,ERRnoaccess));
+#endif /* Needs more testing... */
+
+      /* attributes */
+      mode = IVAL(pdata,32);
       break;
+    }
 
     case SMB_SET_FILE_END_OF_FILE_INFO:
+    {
       if (IVAL(pdata,4) != 0)  /* more than 32 bits? */
-       return(ERROR(ERRDOS,ERRunknownlevel));
+         return(ERROR(ERRDOS,ERRunknownlevel));
       size = IVAL(pdata,0);
       break;
+    }
 
     case SMB_SET_FILE_DISPOSITION_INFO: /* not supported yet */
     case SMB_SET_FILE_ALLOCATION_INFO: /* not supported yet */
     default:
+    {
       return(ERROR(ERRDOS,ERRunknownlevel));
     }
+  }
 
+  DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
+  DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
+  DEBUG(6,("size: %x "   , size));
+  DEBUG(6,("mode: %x\n"  , mode));
 
+  /* get some defaults (no modifications) if any info is zero. */
   if (!tvs.actime) tvs.actime = st.st_atime;
   if (!tvs.modtime) tvs.modtime = st.st_mtime;
   if (!size) size = st.st_size;
 
-  /* Try and set the times, size and mode of this file - if they are different 
-   from the current values */
-  if(st.st_mtime != tvs.modtime || st.st_atime != tvs.actime) {
+  /* Try and set the times, size and mode of this file -
+     if they are different from the current values
+   */
+  if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime)
+  {
     if(sys_utime(fname, &tvs)!=0)
+    {
       return(ERROR(ERRDOS,ERRnoaccess));
+    }
   }
-  if(mode != dos_mode(cnum,fname,&st) && dos_chmod(cnum,fname,mode,NULL)) {
+
+  /* check the mode isn't different, before changing it */
+  if (mode != dos_mode(cnum, fname, &st) && dos_chmod(cnum, fname, mode, NULL))
+  {
     DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
     return(ERROR(ERRDOS,ERRnoaccess));
   }
-  if(size != st.st_size) {
-    if (fd == -1) {
+
+  if(size != st.st_size)
+  {
+    if (fd == -1)
+    {
       fd = sys_open(fname,O_RDWR,0);
       if (fd == -1)
-       return(ERROR(ERRDOS,ERRbadpath));
+      {
+        return(ERROR(ERRDOS,ERRbadpath));
+      }
       set_filelen(fd, size);
       close(fd);
-    } else {
+    }
+    else
+    {
       set_filelen(fd, size);
     }
   }
@@ -1349,21 +1460,27 @@ static int call_trans2mkdir(char *inbuf, char *outbuf, int length, int bufsize,
   char *params = *pparams;
   pstring directory;
   int ret = -1;
+  BOOL bad_path = False;
 
   if (!CAN_WRITE(cnum))
     return(ERROR(ERRSRV,ERRaccess));
 
-  strcpy(directory, &params[4]);
+  pstrcpy(directory, &params[4]);
 
   DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
 
-  unix_convert(directory,cnum,0);
+  unix_convert(directory,cnum,0,&bad_path);
   if (check_name(directory,cnum))
     ret = sys_mkdir(directory,unix_mode(cnum,aDIR));
   
   if(ret < 0)
     {
       DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
+      if((errno == ENOENT) && bad_path)
+      {
+        unix_ERR_class = ERRDOS;
+        unix_ERR_code = ERRbadpath;
+      }
       return(UNIXERROR(ERRDOS,ERRnoaccess));
     }
 
@@ -1550,6 +1667,9 @@ int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize)
   num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
   num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
 
+  if (num_params > total_params || num_data > total_data)
+         exit_server("invalid params in reply_trans2");
+
   memcpy( params, smb_base(inbuf) + SVAL(inbuf, smb_psoff), num_params);
   memcpy( data, smb_base(inbuf) + SVAL(inbuf, smb_dsoff), num_data);
 
@@ -1577,6 +1697,9 @@ int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize)
          total_data = SVAL(inbuf, smb_tdscnt);
          num_params_sofar += (num_params = SVAL(inbuf,smb_spscnt));
          num_data_sofar += ( num_data = SVAL(inbuf, smb_sdscnt));
+         if (num_params_sofar > total_params || num_data_sofar > total_data)
+                 exit_server("data overflow in trans2");
+
          memcpy( &params[ SVAL(inbuf, smb_spsdisp)], 
                 smb_base(inbuf) + SVAL(inbuf, smb_spsoff), num_params);
          memcpy( &data[SVAL(inbuf, smb_sdsdisp)],