Implementing more NT SMB functionality.
authorJeremy Allison <jra@samba.org>
Wed, 8 Jul 1998 01:42:05 +0000 (01:42 +0000)
committerJeremy Allison <jra@samba.org>
Wed, 8 Jul 1998 01:42:05 +0000 (01:42 +0000)
Jeremy.

source/smbd/nttrans.c

index 5327502fd3726a664aa03734b216c3e5e8cf50dd..c8901537813fad34f011feb380542457fcb0c242 100644 (file)
@@ -89,80 +89,41 @@ static void restore_case_semantics(uint32 file_attributes)
 }
 
 /****************************************************************************
 reply to an NT create and X call.
Utility function to map create disposition.
 ****************************************************************************/
 
-int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize)
-{  
-  pstring fname;
-  int cnum = SVAL(inbuf,smb_tid);
-  int fnum = -1;
-  uint32 flags = SIVAL(inbuf,smb_ntcreate_Flags);
-  uint32 desired_access = SIVAL(inbuf,smb_ntcreate_DesiredAccess);
-  uint32 file_attributes = SIVAL(inbuf,smb_ntcreate_FileAttributes);
-  uint32 share_access = SIVAL(inbuf,smb_ntcreate_ShareAccess);
-  uint32 create_disposition = SIVAL(inbuf,smb_ntcreate_CreateDisposition);
-  uint32 fname_len = MIN(((uint32)SSVAL(inbuf,smb_ntcreate_NameLength)),
-                         ((uint32)sizeof(fname)-1));
-  int smb_ofun;
-  int smb_open_mode;
-  int smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK);
-  /* Breakout the oplock request bits so we can set the
-     reply bits separately. */
-  int oplock_request = flags & (REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK);
-  int unixmode;
-  int fmode=0,mtime=0,rmode=0;
-  off_t file_size = 0;
-  struct stat sbuf;
-  int smb_action = 0;
-  BOOL bad_path = False;
-  files_struct *fsp;
-  char *p = NULL;
-  
-  /* If it's an IPC, pass off the pipe handler. */
-  if (IS_IPC(cnum))
-    return nt_open_pipe_and_X(inbuf,outbuf,length,bufsize);
-
-  /* If it's a request for a directory open, fail it. */
-  if(flags & OPEN_DIRECTORY)
-    return(ERROR(ERRDOS,ERRnoaccess));
-
-  /* 
-   * We need to construct the open_and_X ofun value from the
-   * NT values, as that's what our code is structured to accept.
-   */    
-
+static int map_create_disposition( uint32 create_disposition)
+{
   switch( create_disposition ) {
   case CREATE_NEW:
     /* create if not exist, fail if exist */
-    smb_ofun = 0x10;
-    break;
+    return 0x10;
   case CREATE_ALWAYS:
     /* create if not exist, trunc if exist */
-    smb_ofun = 0x12;
-    break;
+    return 0x12;
   case OPEN_EXISTING:
     /* fail if not exist, open if exists */
-    smb_ofun = 0x1;
-    break;
+    return 0x1;
   case OPEN_ALWAYS:
     /* create if not exist, open if exists */
-    smb_ofun = 0x11;
-    break;
+    return 0x11;
   case TRUNCATE_EXISTING:
     /* fail if not exist, truncate if exists */
-    smb_ofun = 0x2;
-    break;
+    return 0x2;
   default:
-    DEBUG(0,("reply_ntcreate_and_X: Incorrect value for create_disposition = %d\n",
+    DEBUG(0,("map_create_disposition: Incorrect value for create_disposition = %d\n",
              create_disposition ));
-    return(ERROR(ERRDOS,ERRbadaccess));
+    return -1;
   }
+}
 
-  /*
-   * Now contruct the smb_open_mode value from the desired access
-   * and the share access.
-   */
+/****************************************************************************
+ Utility function to map share modes.
+****************************************************************************/
+
+static int map_share_mode( uint32 desired_access, uint32 share_access)
+{
+  int smb_open_mode;
 
   switch( desired_access & (FILE_READ_DATA|FILE_WRITE_DATA) ) {
   case FILE_READ_DATA:
@@ -175,9 +136,9 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize)
     smb_open_mode = 2;
     break;
   default:
-    DEBUG(0,("reply_ntcreate_and_X: Incorrect value for desired_access = %x\n",
+    DEBUG(0,("map_share_mode: Incorrect value for desired_access = %x\n",
              desired_access));
-    return(ERROR(ERRDOS,ERRbadaccess));
+    return -1;
   }
 
   /* Add in the requested share mode - ignore FILE_SHARE_DELETE for now. */
@@ -202,6 +163,121 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize)
   if(file_attributes & FILE_FLAG_WRITE_THROUGH)
     smb_open_mode |= (1<<14);
 
+  return smb_open_mode;
+}
+
+/****************************************************************************
+ Reply to an NT create and X call on a pipe.
+****************************************************************************/
+
+static int nt_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize)
+{
+  pstring fname;
+  int cnum = SVAL(inbuf,smb_tid);
+  int pnum = -1;
+  uint16 vuid = SVAL(inbuf, smb_uid);
+  uint32 flags = IVAL(inbuf,smb_ntcreate_Flags);
+  uint32 desired_access = IVAL(inbuf,smb_ntcreate_DesiredAccess);
+  uint32 file_attributes = IVAL(inbuf,smb_ntcreate_FileAttributes);
+  uint32 share_access = IVAL(inbuf,smb_ntcreate_ShareAccess);
+  uint32 create_disposition = IVAL(inbuf,smb_ntcreate_CreateDisposition);
+  uint32 fname_len = MIN(((uint32)SVAL(inbuf,smb_ntcreate_NameLength)),
+                         ((uint32)sizeof(fname)-1));
+  int smb_ofun;
+  int smb_open_mode;
+  int smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK);
+  int unixmode;
+  int fmode=0,mtime=0,rmode=0;
+  off_t file_size = 0;
+  struct stat sbuf;
+  int smb_action = 0;
+  BOOL bad_path = False;
+  files_struct *fsp;
+  char *p = NULL;
+
+  StrnCpy(fname,smb_buf(inbuf),fname_len);
+    
+  DEBUG(4,("nt_open_pipe_and_X: Opening pipe %s.\n", fname));
+    
+  /* See if it is one we want to handle. */
+  for( i = 0; known_nt_pipes[i]; i++ )
+    if( strequal(fname,known_nt_pipes[i]))
+      break;
+    
+  if ( known_nt_pipes[i] == NULL )
+    return(ERROR(ERRSRV,ERRaccess));
+    
+  /* Strip \\ off the name. */
+  p = &fname[1];
+    
+  /* Known pipes arrive with DIR attribs. Remove it so a regular file */
+  /* can be opened and add it in after the open. */
+  DEBUG(3,("nt_open_pipe_and_X: Known pipe %s opening.\n",p));
+
+  if((smb_ofun = map_create_disposition( create_disposition )) == -1)
+    return(ERROR(ERRDOS,ERRbadaccess));
+  smb_ofun |= 0x10;     /* Add Create it not exists flag */
+    
+  pnum = open_rpc_pipe_hnd(p, cnum, vuid);
+  if (pnum < 0)
+    return(ERROR(ERRSRV,ERRnofids));
+}
+
+/****************************************************************************
+ Reply to an NT create and X call.
+****************************************************************************/
+
+int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize)
+{  
+  pstring fname;
+  int cnum = SVAL(inbuf,smb_tid);
+  int fnum = -1;
+  uint32 flags = IVAL(inbuf,smb_ntcreate_Flags);
+  uint32 desired_access = IVAL(inbuf,smb_ntcreate_DesiredAccess);
+  uint32 file_attributes = IVAL(inbuf,smb_ntcreate_FileAttributes);
+  uint32 share_access = IVAL(inbuf,smb_ntcreate_ShareAccess);
+  uint32 create_disposition = IVAL(inbuf,smb_ntcreate_CreateDisposition);
+  uint32 fname_len = MIN(((uint32)SVAL(inbuf,smb_ntcreate_NameLength)),
+                         ((uint32)sizeof(fname)-1));
+  int smb_ofun;
+  int smb_open_mode;
+  int smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK);
+  /* Breakout the oplock request bits so we can set the
+     reply bits separately. */
+  int oplock_request = flags & (REQUEST_OPLOCK|REQUEST_BATCH_OPLOCK);
+  int unixmode;
+  int fmode=0,mtime=0,rmode=0;
+  off_t file_size = 0;
+  struct stat sbuf;
+  int smb_action = 0;
+  BOOL bad_path = False;
+  files_struct *fsp;
+  char *p = NULL;
+  
+  /* If it's an IPC, pass off the pipe handler. */
+  if (IS_IPC(cnum))
+    return nt_open_pipe_and_X(inbuf,outbuf,length,bufsize);
+
+  /* If it's a request for a directory open, fail it. */
+  if(flags & OPEN_DIRECTORY)
+    return(ERROR(ERRDOS,ERRnoaccess));
+
+  /* 
+   * We need to construct the open_and_X ofun value from the
+   * NT values, as that's what our code is structured to accept.
+   */    
+
+  if((smb_ofun = map_create_disposition( create_disposition )) == -1)
+    return(ERROR(ERRDOS,ERRbadaccess));
+
+  /*
+   * Now contruct the smb_open_mode value from the desired access
+   * and the share access.
+   */
+
+  if((smb_open_mode = map_share_mode( desired_access, share_access)) == -1)
+    return(ERROR(ERRDOS,ERRbadaccess));
+
   /*
    * Check if POSIX semantics are wanted.
    */
@@ -256,14 +332,13 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize)
     return(ERROR(ERRDOS,ERRnoaccess));
   } 
   
+  restore_case_semantics(file_attributes);
+
   size = sbuf.st_size;
   fmode = dos_mode(cnum,fname,&sbuf);
   mtime = sbuf.st_mtime;
   if (fmode & aDIR) {
     close_file(fnum,False);
-
-    restore_case_semantics(file_attributes);
-
     return(ERROR(ERRDOS,ERRnoaccess));
   } 
   
@@ -312,33 +387,141 @@ int reply_ntcreate_and_X(char *inbuf,char *outbuf,int length,int bufsize)
 
   chain_fnum = fnum;
     
-  restore_case_semantics(file_attributes);
-
   return chain_reply(inbuf,outbuf,length,bufsize);
 }
 
 /****************************************************************************
reply to a NT_TRANSACT_CREATE call (needs to process SD's).
Reply to a NT_TRANSACT_CREATE call (needs to process SD's).
 ****************************************************************************/
 
 static int call_nt_transact_create(char *inbuf, char *outbuf, int bufsize, int cnum,
                                    char **setup, char **params, char **data)
 {
+  pstring fname;
+  int fnum = -1;
   char *params = *pparams;
-  uint32 flags = SIVAL(params,0);
-  uint32 desired_access = 
-  uint32 file_attributes = SIVAL(inbuf,smb_ntcreate_FileAttributes);
-  uint32 share_access = SIVAL(inbuf,smb_ntcreate_ShareAccess);
-  uint32 create_disposition = SIVAL(inbuf,smb_ntcreate_CreateDisposition);
-  uint32 fname_len = MIN(((uint32)SSVAL(inbuf,smb_ntcreate_NameLength)),
+  uint32 flags = IVAL(params,0);
+  uint32 desired_access = IVAL(params,8);
+  uint32 file_attributes = IVAL(params,20);
+  uint32 share_access = IVAL(params,24);
+  uint32 create_disposition = IVAL(params,28);
+  uint32 fname_len = MIN(((uint32)IVAL(params,44)),
                          ((uint32)sizeof(fname)-1));
   int smb_ofun;
   int smb_open_mode;
   int smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK);
+
+  /* If it's a request for a directory open, fail it. */
+  if(flags & OPEN_DIRECTORY)
+    return(ERROR(ERRDOS,ERRnoaccess));
+
+  /* 
+   * We need to construct the open_and_X ofun value from the
+   * NT values, as that's what our code is structured to accept.
+   */    
+
+  if((smb_ofun = map_create_disposition( create_disposition )) == -1)
+    return(ERROR(ERRDOS,ERRbadaccess));
+
+  /*
+   * Now contruct the smb_open_mode value from the desired access
+   * and the share access.
+   */
+
+  if((smb_open_mode = map_share_mode( desired_access, share_access)) == -1)
+    return(ERROR(ERRDOS,ERRbadaccess));
+
+  /*
+   * Check if POSIX semantics are wanted.
+   */
+
+  set_posix_case_semantics(file_attributes);
+
+  StrnCpy(fname,params+53,fname_len);
+  unix_convert(fname,cnum,0,&bad_path);
+    
+  fnum = find_free_file();
+  if (fnum < 0) {
+    restore_case_semantics(file_attributes);
+    return(ERROR(ERRSRV,ERRnofids));
+  }
+
+  if (!check_name(fname,cnum)) { 
+    if((errno == ENOENT) && bad_path) {
+      unix_ERR_class = ERRDOS;
+      unix_ERR_code = ERRbadpath;
+    }
+    Files[fnum].reserved = False;
+
+    restore_case_semantics(file_attributes);
+
+    return(UNIXERROR(ERRDOS,ERRnoaccess));
+  } 
+  
+  unixmode = unix_mode(cnum,smb_attr | aARCH);
+    
+  open_file_shared(fnum,cnum,fname,smb_open_mode,smb_ofun,unixmode,
+                   oplock_request,&rmode,&smb_action);
+
+  fsp = &Files[fnum];
+    
+  if (!fsp->open) { 
+    if((errno == ENOENT) && bad_path) {
+      unix_ERR_class = ERRDOS;
+      unix_ERR_code = ERRbadpath;
+    }
+    Files[fnum].reserved = False;
+
+    restore_case_semantics(file_attributes);
+
+    return(UNIXERROR(ERRDOS,ERRnoaccess));
+  } 
+  
+  if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
+    close_file(fnum,False);
+
+    restore_case_semantics(file_attributes);
+
+    return(ERROR(ERRDOS,ERRnoaccess));
+  } 
+  
+  restore_case_semantics(file_attributes);
+
+  size = sbuf.st_size;
+  fmode = dos_mode(cnum,fname,&sbuf);
+  mtime = sbuf.st_mtime;
+  if (fmode & aDIR) {
+    close_file(fnum,False);
+    return(ERROR(ERRDOS,ERRnoaccess));
+  } 
+  
+  /* If the caller set the extended oplock request bit
+     and we granted one (by whatever means) - set the
+     correct bit for extended oplock reply.
+   */
+    
+  if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
+    smb_action |= EXTENDED_OPLOCK_GRANTED;
+  } 
+  
+  if(oplock_request && fsp->granted_oplock) {
+    smb_action |= EXTENDED_OPLOCK_GRANTED;
+  } 
+
 }
 
 /****************************************************************************
-  reply to an unsolicited SMBNTtranss - just ignore it!
+ Reply to a NT CANCEL request - just ignore it.
+****************************************************************************/
+
+int reply_ntcancel(char *inbuf,char *outbuf,int length,int bufsize)
+{
+  DEBUG(4,("Ignoring ntcancel of length %d\n",length));
+  return(-1);
+}
+
+/****************************************************************************
+ Reply to an unsolicited SMBNTtranss - just ignore it!
 ****************************************************************************/
 
 int reply_nttranss(char *inbuf,char *outbuf,int length,int bufsize)
@@ -348,7 +531,74 @@ int reply_nttranss(char *inbuf,char *outbuf,int length,int bufsize)
 }
 
 /****************************************************************************
-  reply to a SMBNTtrans
+ Reply to an NT transact rename command.
+****************************************************************************/
+
+static int call_nt_transact_rename(char *inbuf, char *outbuf, int bufsize, int cnum,
+                                   char **setup, char **params, char **data)
+{
+  char *params = *pparams;
+  pstring fname;
+  int fnum = SVAL(params, 0);
+  uint16 rename_flags = SVAL(params,2);
+  uint32 total_parameter_count = IVAL(inbuf, smb_nt_TotalParameterCount);
+  uint32 fname_len = MIN((((uint32)IVAL(inbuf,smb_nt_TotalParameterCount)-4)),
+                         ((uint32)sizeof(fname)-1));
+
+  StrnCpy(fname,params+4,fname_len);
+  unix_convert(fname,cnum,0,&bad_path);
+    
+}
+   
+/****************************************************************************
+ Reply to a notify change - we should never get this (for now) as we
+ don't allow a directory to be opened.
+****************************************************************************/
+
+static int call_nt_transact_notify_change(char *inbuf, char *outbuf, int bufsize, int cnum,
+                                          char **setup, char **params, char **data)
+{
+  DEBUG(0,("call_nt_transact_notify_change: Should not be called !\n"));
+  return(ERROR(ERRSRV,ERRnosupport));
+}
+   
+/****************************************************************************
+ Reply to query a security descriptor - currently this is not implemented (it
+ is planned to be though).
+****************************************************************************/
+
+static int call_nt_transact_query_security_desc(char *inbuf, char *outbuf, int bufsize, int cnum,
+                                                char **setup, char **params, char **data)
+{
+  DEBUG(0,("call_nt_transact_query_security_desc: Currently not implemented.\n"));
+  return(ERROR(ERRSRV,ERRnosupport));
+}
+   
+/****************************************************************************
+ Reply to set a security descriptor - currently this is not implemented (it
+ is planned to be though).
+****************************************************************************/
+
+static int call_nt_transact_set_security_desc(char *inbuf, char *outbuf, int bufsize, int cnum,
+                                              char **setup, char **params, char **data)
+{
+  DEBUG(0,("call_nt_transact_set_security_desc: Currently not implemented.\n"));
+  return(ERROR(ERRSRV,ERRnosupport));
+}
+   
+/****************************************************************************
+ Reply to IOCTL - not implemented - no plans.
+****************************************************************************/
+
+static int call_nt_transact_ioctl(char *inbuf, char *outbuf, int bufsize, int cnum,
+                                  char **setup, char **params, char **data)
+{
+  DEBUG(0,("call_nt_transact_ioctl: Currently not implemented.\n"));
+  return(ERROR(ERRSRV,ERRnosupport));
+}
+   
+/****************************************************************************
+ Reply to a SMBNTtrans.
 ****************************************************************************/
 
 int reply_nttrans(char *inbuf,char *outbuf,int length,int bufsize)
@@ -366,7 +616,7 @@ int reply_nttrans(char *inbuf,char *outbuf,int length,int bufsize)
   uint32 parameter_offset = IVAL(inbuf,smb_nt_ParameterOffset);
   uint32 data_count = IVAL(inbuf,smb_nt_DataCount);
   uint32 data_offset = IVAL(inbuf,smb_nt_DataOffset);
-  uint16 setup_count = SVAL(inbuf,smb_nt_SetupCount);
+  uint16 setup_count = CVAL(inbuf,smb_nt_SetupCount);
   uint16 function_code = SVAL( inbuf, smb_nt_Function);
   char *params = NULL, *data = NULL, *setup = NULL;
   uint32 num_params_sofar, num_data_sofar;
@@ -454,17 +704,17 @@ due to being in oplock break state.\n", timestring() ));
       }
       
       /* Revise total_params and total_data in case they have changed downwards */
-      total_parameter_count = SIVAL(inbuf, smb_nts_TotalParameterCount);
-      total_data_count = SIVAL(inbuf, smb_nts_TotalDataCount);
-      num_params_sofar += (parameter_count = SIVAL(inbuf,smb_nts_ParameterCount));
-      num_data_sofar += ( data_count = SIVAL(inbuf, smb_nts_DataCount));
+      total_parameter_count = IVAL(inbuf, smb_nts_TotalParameterCount);
+      total_data_count = IVAL(inbuf, smb_nts_TotalDataCount);
+      num_params_sofar += (parameter_count = IVAL(inbuf,smb_nts_ParameterCount));
+      num_data_sofar += ( data_count = IVAL(inbuf, smb_nts_DataCount));
       if (num_params_sofar > total_parameter_count || num_data_sofar > total_data_count)
         exit_server("reply_nttrans2: data overflow in secondary nttrans packet\n");
 
-      memcpy( &params[ SIVAL(inbuf, smb_nts_ParameterDisplacement)], 
-              smb_base(inbuf) + SVAL(inbuf, smb_nts_ParameterOffset), parameter_count);
-      memcpy( &data[SVAL(inbuf, smb_nts_DataDisplacement)],
-              smb_base(inbuf)+ SVAL(inbuf, smb_nts_DataOffset), data_count);
+      memcpy( &params[ IVAL(inbuf, smb_nts_ParameterDisplacement)], 
+              smb_base(inbuf) + IVAL(inbuf, smb_nts_ParameterOffset), parameter_count);
+      memcpy( &data[IVAL(inbuf, smb_nts_DataDisplacement)],
+              smb_base(inbuf)+ IVAL(inbuf, smb_nts_DataOffset), data_count);
     }
   }