smbd/nttrans.c

説明を見る。
00001 /*
00002    Unix SMB/CIFS implementation.
00003    SMB NT transaction handling
00004    Copyright (C) Jeremy Allison                 1994-1998
00005    Copyright (C) Stefan (metze) Metzmacher      2003
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program; if not, write to the Free Software
00019    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00020 */
00021 
00022 #include "includes.h"
00023 
00024 extern int max_send;
00025 extern enum protocol_types Protocol;
00026 extern int smb_read_error;
00027 extern struct current_user current_user;
00028 
00029 static const char *known_nt_pipes[] = {
00030         "\\LANMAN",
00031         "\\srvsvc",
00032         "\\samr",
00033         "\\wkssvc",
00034         "\\NETLOGON",
00035         "\\ntlsa",
00036         "\\ntsvcs",
00037         "\\lsass",
00038         "\\lsarpc",
00039         "\\winreg",
00040         "\\initshutdown",
00041         "\\spoolss",
00042         "\\netdfs",
00043         "\\rpcecho",
00044         "\\svcctl",
00045         "\\eventlog",
00046         "\\unixinfo",
00047         NULL
00048 };
00049 
00050 static char *nttrans_realloc(char **ptr, size_t size)
00051 {
00052         if (ptr==NULL) {
00053                 smb_panic("nttrans_realloc() called with NULL ptr\n");
00054         }
00055                 
00056         *ptr = (char *)SMB_REALLOC(*ptr, size);
00057         if(*ptr == NULL) {
00058                 return NULL;
00059         }
00060         memset(*ptr,'\0',size);
00061         return *ptr;
00062 }
00063 
00064 /****************************************************************************
00065  Send the required number of replies back.
00066  We assume all fields other than the data fields are
00067  set correctly for the type of call.
00068  HACK ! Always assumes smb_setup field is zero.
00069 ****************************************************************************/
00070 
00071 int send_nt_replies(char *outbuf, int bufsize, NTSTATUS nt_error,
00072                     char *params, int paramsize, char *pdata, int datasize)
00073 {
00074         int data_to_send = datasize;
00075         int params_to_send = paramsize;
00076         int useable_space;
00077         char *pp = params;
00078         char *pd = pdata;
00079         int params_sent_thistime, data_sent_thistime, total_sent_thistime;
00080         int alignment_offset = 3;
00081         int data_alignment_offset = 0;
00082 
00083         /*
00084          * Initially set the wcnt area to be 18 - this is true for all
00085          * transNT replies.
00086          */
00087 
00088         set_message(outbuf,18,0,True);
00089 
00090         if (NT_STATUS_V(nt_error)) {
00091                 ERROR_NT(nt_error);
00092         }
00093 
00094         /* 
00095          * If there genuinely are no parameters or data to send just send
00096          * the empty packet.
00097          */
00098 
00099         if(params_to_send == 0 && data_to_send == 0) {
00100                 show_msg(outbuf);
00101                 if (!send_smb(smbd_server_fd(),outbuf)) {
00102                         exit_server_cleanly("send_nt_replies: send_smb failed.");
00103                 }
00104                 return 0;
00105         }
00106 
00107         /*
00108          * When sending params and data ensure that both are nicely aligned.
00109          * Only do this alignment when there is also data to send - else
00110          * can cause NT redirector problems.
00111          */
00112 
00113         if (((params_to_send % 4) != 0) && (data_to_send != 0)) {
00114                 data_alignment_offset = 4 - (params_to_send % 4);
00115         }
00116 
00117         /* 
00118          * Space is bufsize minus Netbios over TCP header minus SMB header.
00119          * The alignment_offset is to align the param bytes on a four byte
00120          * boundary (2 bytes for data len, one byte pad). 
00121          * NT needs this to work correctly.
00122          */
00123 
00124         useable_space = bufsize - ((smb_buf(outbuf)+
00125                                 alignment_offset+data_alignment_offset) -
00126                                 outbuf);
00127 
00128         /*
00129          * useable_space can never be more than max_send minus the
00130          * alignment offset.
00131          */
00132 
00133         useable_space = MIN(useable_space,
00134                                 max_send - (alignment_offset+data_alignment_offset));
00135 
00136 
00137         while (params_to_send || data_to_send) {
00138 
00139                 /*
00140                  * Calculate whether we will totally or partially fill this packet.
00141                  */
00142 
00143                 total_sent_thistime = params_to_send + data_to_send +
00144                                         alignment_offset + data_alignment_offset;
00145 
00146                 /* 
00147                  * We can never send more than useable_space.
00148                  */
00149 
00150                 total_sent_thistime = MIN(total_sent_thistime, useable_space);
00151 
00152                 set_message(outbuf, 18, total_sent_thistime, True);
00153 
00154                 /*
00155                  * Set total params and data to be sent.
00156                  */
00157 
00158                 SIVAL(outbuf,smb_ntr_TotalParameterCount,paramsize);
00159                 SIVAL(outbuf,smb_ntr_TotalDataCount,datasize);
00160 
00161                 /* 
00162                  * Calculate how many parameters and data we can fit into
00163                  * this packet. Parameters get precedence.
00164                  */
00165 
00166                 params_sent_thistime = MIN(params_to_send,useable_space);
00167                 data_sent_thistime = useable_space - params_sent_thistime;
00168                 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
00169 
00170                 SIVAL(outbuf,smb_ntr_ParameterCount,params_sent_thistime);
00171 
00172                 if(params_sent_thistime == 0) {
00173                         SIVAL(outbuf,smb_ntr_ParameterOffset,0);
00174                         SIVAL(outbuf,smb_ntr_ParameterDisplacement,0);
00175                 } else {
00176                         /*
00177                          * smb_ntr_ParameterOffset is the offset from the start of the SMB header to the
00178                          * parameter bytes, however the first 4 bytes of outbuf are
00179                          * the Netbios over TCP header. Thus use smb_base() to subtract
00180                          * them from the calculation.
00181                          */
00182 
00183                         SIVAL(outbuf,smb_ntr_ParameterOffset,
00184                                 ((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
00185                         /* 
00186                          * Absolute displacement of param bytes sent in this packet.
00187                          */
00188 
00189                         SIVAL(outbuf,smb_ntr_ParameterDisplacement,pp - params);
00190                 }
00191 
00192                 /*
00193                  * Deal with the data portion.
00194                  */
00195 
00196                 SIVAL(outbuf,smb_ntr_DataCount, data_sent_thistime);
00197 
00198                 if(data_sent_thistime == 0) {
00199                         SIVAL(outbuf,smb_ntr_DataOffset,0);
00200                         SIVAL(outbuf,smb_ntr_DataDisplacement, 0);
00201                 } else {
00202                         /*
00203                          * The offset of the data bytes is the offset of the
00204                          * parameter bytes plus the number of parameters being sent this time.
00205                          */
00206 
00207                         SIVAL(outbuf,smb_ntr_DataOffset,((smb_buf(outbuf)+alignment_offset) -
00208                                 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
00209                                 SIVAL(outbuf,smb_ntr_DataDisplacement, pd - pdata);
00210                 }
00211 
00212                 /* 
00213                  * Copy the param bytes into the packet.
00214                  */
00215 
00216                 if(params_sent_thistime) {
00217                         memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
00218                 }
00219 
00220                 /*
00221                  * Copy in the data bytes
00222                  */
00223 
00224                 if(data_sent_thistime) {
00225                         memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
00226                                 data_alignment_offset,pd,data_sent_thistime);
00227                 }
00228     
00229                 DEBUG(9,("nt_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
00230                         params_sent_thistime, data_sent_thistime, useable_space));
00231                 DEBUG(9,("nt_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
00232                         params_to_send, data_to_send, paramsize, datasize));
00233     
00234                 /* Send the packet */
00235                 show_msg(outbuf);
00236                 if (!send_smb(smbd_server_fd(),outbuf)) {
00237                         exit_server_cleanly("send_nt_replies: send_smb failed.");
00238                 }
00239     
00240                 pp += params_sent_thistime;
00241                 pd += data_sent_thistime;
00242     
00243                 params_to_send -= params_sent_thistime;
00244                 data_to_send -= data_sent_thistime;
00245 
00246                 /*
00247                  * Sanity check
00248                  */
00249 
00250                 if(params_to_send < 0 || data_to_send < 0) {
00251                         DEBUG(0,("send_nt_replies failed sanity check pts = %d, dts = %d\n!!!",
00252                                 params_to_send, data_to_send));
00253                         return -1;
00254                 }
00255         } 
00256 
00257         return 0;
00258 }
00259 
00260 /****************************************************************************
00261  Is it an NTFS stream name ?
00262 ****************************************************************************/
00263 
00264 BOOL is_ntfs_stream_name(const char *fname)
00265 {
00266         if (lp_posix_pathnames()) {
00267                 return False;
00268         }
00269         return (strchr_m(fname, ':') != NULL) ? True : False;
00270 }
00271 
00272 /****************************************************************************
00273  Save case statics.
00274 ****************************************************************************/
00275 
00276 static BOOL saved_case_sensitive;
00277 static BOOL saved_case_preserve;
00278 static BOOL saved_short_case_preserve;
00279 
00280 /****************************************************************************
00281  Save case semantics.
00282 ****************************************************************************/
00283 
00284 static uint32 set_posix_case_semantics(connection_struct *conn, uint32 file_attributes)
00285 {
00286         if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) {
00287                 return file_attributes;
00288         }
00289 
00290         saved_case_sensitive = conn->case_sensitive;
00291         saved_case_preserve = conn->case_preserve;
00292         saved_short_case_preserve = conn->short_case_preserve;
00293 
00294         /* Set to POSIX. */
00295         conn->case_sensitive = True;
00296         conn->case_preserve = True;
00297         conn->short_case_preserve = True;
00298 
00299         return (file_attributes & ~FILE_FLAG_POSIX_SEMANTICS);
00300 }
00301 
00302 /****************************************************************************
00303  Restore case semantics.
00304 ****************************************************************************/
00305 
00306 static void restore_case_semantics(connection_struct *conn, uint32 file_attributes)
00307 {
00308         if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) {
00309                 return;
00310         }
00311 
00312         conn->case_sensitive = saved_case_sensitive;
00313         conn->case_preserve = saved_case_preserve;
00314         conn->short_case_preserve = saved_short_case_preserve;
00315 }
00316 
00317 /****************************************************************************
00318  Reply to an NT create and X call on a pipe.
00319 ****************************************************************************/
00320 
00321 static int nt_open_pipe(char *fname, connection_struct *conn,
00322                         char *inbuf, char *outbuf, int *ppnum)
00323 {
00324         smb_np_struct *p = NULL;
00325         uint16 vuid = SVAL(inbuf, smb_uid);
00326         int i;
00327  
00328         DEBUG(4,("nt_open_pipe: Opening pipe %s.\n", fname));
00329     
00330         /* See if it is one we want to handle. */
00331 
00332         if (lp_disable_spoolss() && strequal(fname, "\\spoolss")) {
00333                 return(ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpipe));
00334         }
00335 
00336         for( i = 0; known_nt_pipes[i]; i++ ) {
00337                 if( strequal(fname,known_nt_pipes[i])) {
00338                         break;
00339                 }
00340         }
00341     
00342         if ( known_nt_pipes[i] == NULL ) {
00343                 return(ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpipe));
00344         }
00345     
00346         /* Strip \\ off the name. */
00347         fname++;
00348     
00349         DEBUG(3,("nt_open_pipe: Known pipe %s opening.\n", fname));
00350 
00351         p = open_rpc_pipe_p(fname, conn, vuid);
00352         if (!p) {
00353                 return(ERROR_DOS(ERRSRV,ERRnofids));
00354         }
00355 
00356         /* Add pipe to db */
00357         
00358         if ( !store_pipe_opendb( p ) ) {
00359                 DEBUG(3,("nt_open_pipe: failed to store %s pipe open.\n", fname));
00360         }
00361         
00362         *ppnum = p->pnum;
00363         return 0;
00364 }
00365 
00366 /****************************************************************************
00367  Reply to an NT create and X call for pipes.
00368 ****************************************************************************/
00369 
00370 static int do_ntcreate_pipe_open(connection_struct *conn,
00371                          char *inbuf,char *outbuf,int length,int bufsize)
00372 {
00373         pstring fname;
00374         int ret;
00375         int pnum = -1;
00376         char *p = NULL;
00377         uint32 flags = IVAL(inbuf,smb_ntcreate_Flags);
00378 
00379         srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE);
00380 
00381         if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0) {
00382                 return ret;
00383         }
00384 
00385         /*
00386          * Deal with pipe return.
00387          */  
00388 
00389         if (flags & EXTENDED_RESPONSE_REQUIRED) {
00390                 /* This is very strange. We
00391                  * return 50 words, but only set
00392                  * the wcnt to 42 ? It's definately
00393                  * what happens on the wire....
00394                  */
00395                 set_message(outbuf,50,0,True);
00396                 SCVAL(outbuf,smb_wct,42);
00397         } else {
00398                 set_message(outbuf,34,0,True);
00399         }
00400 
00401         p = outbuf + smb_vwv2;
00402         p++;
00403         SSVAL(p,0,pnum);
00404         p += 2;
00405         SIVAL(p,0,FILE_WAS_OPENED);
00406         p += 4;
00407         p += 32;
00408         SIVAL(p,0,FILE_ATTRIBUTE_NORMAL); /* File Attributes. */
00409         p += 20;
00410         /* File type. */
00411         SSVAL(p,0,FILE_TYPE_MESSAGE_MODE_PIPE);
00412         /* Device state. */
00413         SSVAL(p,2, 0x5FF); /* ? */
00414         p += 4;
00415 
00416         if (flags & EXTENDED_RESPONSE_REQUIRED) {
00417                 p += 25;
00418                 SIVAL(p,0,FILE_GENERIC_ALL);
00419                 /* 
00420                  * For pipes W2K3 seems to return
00421                  * 0x12019B next.
00422                  * This is ((FILE_GENERIC_READ|FILE_GENERIC_WRITE) & ~FILE_APPEND_DATA)
00423                  */
00424                 SIVAL(p,4,(FILE_GENERIC_READ|FILE_GENERIC_WRITE)&~FILE_APPEND_DATA);
00425         }
00426 
00427         DEBUG(5,("do_ntcreate_pipe_open: open pipe = %s\n", fname));
00428 
00429         return chain_reply(inbuf,outbuf,length,bufsize);
00430 }
00431 
00432 /****************************************************************************
00433  Reply to an NT create and X call for a quota file.
00434 ****************************************************************************/
00435 
00436 int reply_ntcreate_and_X_quota(connection_struct *conn,
00437                                 char *inbuf,
00438                                 char *outbuf,
00439                                 int length,
00440                                 int bufsize,
00441                                 enum FAKE_FILE_TYPE fake_file_type,
00442                                 const char *fname)
00443 {
00444         int result;
00445         char *p;
00446         uint32 desired_access = IVAL(inbuf,smb_ntcreate_DesiredAccess);
00447         files_struct *fsp;
00448         NTSTATUS status;
00449 
00450         status = open_fake_file(conn, fake_file_type, fname, desired_access,
00451                                 &fsp);
00452 
00453         if (!NT_STATUS_IS_OK(status)) {
00454                 return ERROR_NT(status);
00455         }
00456 
00457         set_message(outbuf,34,0,True);
00458         
00459         p = outbuf + smb_vwv2;
00460         
00461         /* SCVAL(p,0,NO_OPLOCK_RETURN); */
00462         p++;
00463         SSVAL(p,0,fsp->fnum);
00464 
00465         DEBUG(5,("reply_ntcreate_and_X_quota: fnum = %d, open name = %s\n", fsp->fnum, fsp->fsp_name));
00466 
00467         result = chain_reply(inbuf,outbuf,length,bufsize);
00468         return result;
00469 }
00470 
00471 /****************************************************************************
00472  Reply to an NT create and X call.
00473 ****************************************************************************/
00474 
00475 int reply_ntcreate_and_X(connection_struct *conn,
00476                          char *inbuf,char *outbuf,int length,int bufsize)
00477 {  
00478         int result;
00479         pstring fname;
00480         uint32 flags = IVAL(inbuf,smb_ntcreate_Flags);
00481         uint32 access_mask = IVAL(inbuf,smb_ntcreate_DesiredAccess);
00482         uint32 file_attributes = IVAL(inbuf,smb_ntcreate_FileAttributes);
00483         uint32 new_file_attributes;
00484         uint32 share_access = IVAL(inbuf,smb_ntcreate_ShareAccess);
00485         uint32 create_disposition = IVAL(inbuf,smb_ntcreate_CreateDisposition);
00486         uint32 create_options = IVAL(inbuf,smb_ntcreate_CreateOptions);
00487         uint16 root_dir_fid = (uint16)IVAL(inbuf,smb_ntcreate_RootDirectoryFid);
00488         /* Breakout the oplock request bits so we can set the
00489            reply bits separately. */
00490         int oplock_request = 0;
00491         uint32 fattr=0;
00492         SMB_OFF_T file_len = 0;
00493         SMB_STRUCT_STAT sbuf;
00494         int info = 0;
00495         files_struct *fsp = NULL;
00496         char *p = NULL;
00497         struct timespec c_timespec;
00498         struct timespec a_timespec;
00499         struct timespec m_timespec;
00500         BOOL extended_oplock_granted = False;
00501         NTSTATUS status;
00502 
00503         START_PROFILE(SMBntcreateX);
00504 
00505         DEBUG(10,("reply_ntcreate_and_X: flags = 0x%x, access_mask = 0x%x "
00506                   "file_attributes = 0x%x, share_access = 0x%x, "
00507                   "create_disposition = 0x%x create_options = 0x%x "
00508                   "root_dir_fid = 0x%x\n",
00509                         (unsigned int)flags,
00510                         (unsigned int)access_mask,
00511                         (unsigned int)file_attributes,
00512                         (unsigned int)share_access,
00513                         (unsigned int)create_disposition,
00514                         (unsigned int)create_options,
00515                         (unsigned int)root_dir_fid ));
00516 
00517         /*
00518          * If it's an IPC, use the pipe handler.
00519          */
00520 
00521         if (IS_IPC(conn)) {
00522                 if (lp_nt_pipe_support()) {
00523                         END_PROFILE(SMBntcreateX);
00524                         return do_ntcreate_pipe_open(conn,inbuf,outbuf,length,bufsize);
00525                 } else {
00526                         END_PROFILE(SMBntcreateX);
00527                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
00528                 }
00529         }
00530 
00531         if (create_options & FILE_OPEN_BY_FILE_ID) {
00532                 END_PROFILE(SMBntcreateX);
00533                 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
00534         }
00535 
00536         /*
00537          * Get the file name.
00538          */
00539 
00540         if(root_dir_fid != 0) {
00541                 /*
00542                  * This filename is relative to a directory fid.
00543                  */
00544                 pstring rel_fname;
00545                 files_struct *dir_fsp = file_fsp(inbuf,smb_ntcreate_RootDirectoryFid);
00546 
00547                 if(!dir_fsp) {
00548                         END_PROFILE(SMBntcreateX);
00549                         return ERROR_DOS(ERRDOS,ERRbadfid);
00550                 }
00551 
00552                 if(!dir_fsp->is_directory) {
00553 
00554                         srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
00555                         if (!NT_STATUS_IS_OK(status)) {
00556                                 END_PROFILE(SMBntcreateX);
00557                                 return ERROR_NT(status);
00558                         }
00559 
00560                         /*
00561                          * Check to see if this is a mac fork of some kind.
00562                          */
00563 
00564                         if( is_ntfs_stream_name(fname)) {
00565                                 END_PROFILE(SMBntcreateX);
00566                                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
00567                         }
00568 
00569                         /*
00570                           we need to handle the case when we get a
00571                           relative open relative to a file and the
00572                           pathname is blank - this is a reopen!
00573                           (hint from demyn plantenberg)
00574                         */
00575 
00576                         END_PROFILE(SMBntcreateX);
00577                         return(ERROR_DOS(ERRDOS,ERRbadfid));
00578                 }
00579 
00580                 /*
00581                  * Copy in the base directory name.
00582                  */
00583 
00584                 pstrcpy( fname, dir_fsp->fsp_name );
00585 
00586                 if (ISDOT(fname)) {
00587                         fname[0] = '\0';
00588                 } else {
00589                         size_t dir_name_len = strlen(fname);
00590                         /*
00591                          * Ensure it ends in a '\'.
00592                          */
00593 
00594                         if((fname[dir_name_len-1] != '\\') && (fname[dir_name_len-1] != '/')) {
00595                                 pstrcat(fname, "/");
00596                         }
00597                 }
00598 
00599                 srvstr_get_path(inbuf, rel_fname, smb_buf(inbuf), sizeof(rel_fname), 0, STR_TERMINATE, &status);
00600                 if (!NT_STATUS_IS_OK(status)) {
00601                         END_PROFILE(SMBntcreateX);
00602                         return ERROR_NT(status);
00603                 }
00604                 pstrcat(fname, rel_fname);
00605         } else {
00606                 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
00607                 if (!NT_STATUS_IS_OK(status)) {
00608                         END_PROFILE(SMBntcreateX);
00609                         return ERROR_NT(status);
00610                 }
00611 
00612                 /*
00613                  * Check to see if this is a mac fork of some kind.
00614                  */
00615 
00616                 if( is_ntfs_stream_name(fname)) {
00617                         enum FAKE_FILE_TYPE fake_file_type = is_fake_file(fname);
00618                         if (fake_file_type!=FAKE_FILE_TYPE_NONE) {
00619                                 /*
00620                                  * Here we go! support for changing the disk quotas --metze
00621                                  *
00622                                  * We need to fake up to open this MAGIC QUOTA file 
00623                                  * and return a valid FID.
00624                                  *
00625                                  * w2k close this file directly after openening
00626                                  * xp also tries a QUERY_FILE_INFO on the file and then close it
00627                                  */
00628                                 result = reply_ntcreate_and_X_quota(conn, inbuf, outbuf, length, bufsize,
00629                                                                 fake_file_type, fname);
00630                                 END_PROFILE(SMBntcreateX);
00631                                 return result;
00632                         } else {
00633                                 END_PROFILE(SMBntcreateX);
00634                                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
00635                         }
00636                 }
00637         }
00638         
00639         /*
00640          * Now contruct the smb_open_mode value from the filename, 
00641          * desired access and the share access.
00642          */
00643         status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
00644         if (!NT_STATUS_IS_OK(status)) {
00645                 END_PROFILE(SMBntcreateX);
00646                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
00647                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
00648                 }
00649                 return ERROR_NT(status);
00650         }
00651 
00652         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
00653         if (oplock_request) {
00654                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
00655         }
00656 
00657         /*
00658          * Ordinary file or directory.
00659          */
00660                 
00661         /*
00662          * Check if POSIX semantics are wanted.
00663          */
00664                 
00665         new_file_attributes = set_posix_case_semantics(conn, file_attributes);
00666                 
00667         status = unix_convert(conn, fname, False, NULL, &sbuf);
00668         if (!NT_STATUS_IS_OK(status)) {
00669                 restore_case_semantics(conn, file_attributes);
00670                 END_PROFILE(SMBntcreateX);
00671                 return ERROR_NT(status);
00672         }
00673         /* All file access must go through check_name() */
00674         status = check_name(conn, fname);
00675         if (!NT_STATUS_IS_OK(status)) {
00676                 restore_case_semantics(conn, file_attributes);
00677                 END_PROFILE(SMBntcreateX);
00678                 return ERROR_NT(status);
00679         }
00680 
00681         /* This is the correct thing to do (check every time) but can_delete is
00682            expensive (it may have to read the parent directory permissions). So
00683            for now we're not doing it unless we have a strong hint the client
00684            is really going to delete this file. If the client is forcing FILE_CREATE
00685            let the filesystem take care of the permissions. */
00686 
00687         /* Setting FILE_SHARE_DELETE is the hint. */
00688 
00689         if (lp_acl_check_permissions(SNUM(conn))
00690             && (create_disposition != FILE_CREATE)
00691             && (share_access & FILE_SHARE_DELETE)
00692             && (access_mask & DELETE_ACCESS)) {
00693                 if ((dos_mode(conn, fname, &sbuf) & FILE_ATTRIBUTE_READONLY) ||
00694                                 !can_delete_file_in_directory(conn, fname)) {
00695                         restore_case_semantics(conn, file_attributes);
00696                         END_PROFILE(SMBntcreateX);
00697                         return ERROR_NT(NT_STATUS_ACCESS_DENIED);
00698                 }
00699         }
00700 
00701         /*
00702          * If it's a request for a directory open, deal with it separately.
00703          */
00704 
00705         if(create_options & FILE_DIRECTORY_FILE) {
00706 
00707                 /* Can't open a temp directory. IFS kit test. */
00708                 if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) {
00709                         END_PROFILE(SMBntcreateX);
00710                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
00711                 }
00712 
00713                 oplock_request = 0;
00714                 status = open_directory(conn, fname, &sbuf,
00715                                         access_mask,
00716                                         share_access,
00717                                         create_disposition,
00718                                         create_options,
00719                                         new_file_attributes,
00720                                         &info, &fsp);
00721         } else {
00722 
00723                 /*
00724                  * Ordinary file case.
00725                  */
00726 
00727                 /* NB. We have a potential bug here. If we
00728                  * cause an oplock break to ourselves, then we
00729                  * could end up processing filename related
00730                  * SMB requests whilst we await the oplock
00731                  * break response. As we may have changed the
00732                  * filename case semantics to be POSIX-like,
00733                  * this could mean a filename request could
00734                  * fail when it should succeed. This is a rare
00735                  * condition, but eventually we must arrange
00736                  * to restore the correct case semantics
00737                  * before issuing an oplock break request to
00738                  * our client. JRA.  */
00739 
00740                 status = open_file_ntcreate(conn,fname,&sbuf,
00741                                         access_mask,
00742                                         share_access,
00743                                         create_disposition,
00744                                         create_options,
00745                                         new_file_attributes,
00746                                         oplock_request,
00747                                         &info, &fsp);
00748 
00749                 if (!NT_STATUS_IS_OK(status)) {
00750                         /* We cheat here. There are two cases we
00751                          * care about. One is a directory rename,
00752                          * where the NT client will attempt to
00753                          * open the source directory for
00754                          * DELETE access. Note that when the
00755                          * NT client does this it does *not*
00756                          * set the directory bit in the
00757                          * request packet. This is translated
00758                          * into a read/write open
00759                          * request. POSIX states that any open
00760                          * for write request on a directory
00761                          * will generate an EISDIR error, so
00762                          * we can catch this here and open a
00763                          * pseudo handle that is flagged as a
00764                          * directory. The second is an open
00765                          * for a permissions read only, which
00766                          * we handle in the open_file_stat case. JRA.
00767                          */
00768 
00769                         if (NT_STATUS_EQUAL(status,
00770                                             NT_STATUS_FILE_IS_A_DIRECTORY)) {
00771 
00772                                 /*
00773                                  * Fail the open if it was explicitly a non-directory file.
00774                                  */
00775 
00776                                 if (create_options & FILE_NON_DIRECTORY_FILE) {
00777                                         restore_case_semantics(conn, file_attributes);
00778                                         END_PROFILE(SMBntcreateX);
00779                                         return ERROR_FORCE_NT(NT_STATUS_FILE_IS_A_DIRECTORY);
00780                                 }
00781 
00782                                 oplock_request = 0;
00783                                 status = open_directory(conn, fname, &sbuf,
00784                                                         access_mask,
00785                                                         share_access,
00786                                                         create_disposition,
00787                                                         create_options,
00788                                                         new_file_attributes,
00789                                                         &info, &fsp);
00790 
00791                         }
00792                 }
00793         }
00794 
00795         restore_case_semantics(conn, file_attributes);
00796 
00797         if(!NT_STATUS_IS_OK(status)) {
00798                 END_PROFILE(SMBntcreateX);
00799 
00800                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
00801                         /* We have re-scheduled this call. */
00802                         return -1;
00803                 }
00804 
00805                 return ERROR_OPEN(status);
00806         }
00807 
00808         file_len = sbuf.st_size;
00809         fattr = dos_mode(conn,fname,&sbuf);
00810         if(fattr == 0) {
00811                 fattr = FILE_ATTRIBUTE_NORMAL;
00812         }
00813         if (!fsp->is_directory && (fattr & aDIR)) {
00814                 close_file(fsp,ERROR_CLOSE);
00815                 END_PROFILE(SMBntcreateX);
00816                 return ERROR_DOS(ERRDOS,ERRnoaccess);
00817         } 
00818         
00819         /* Save the requested allocation size. */
00820         if ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN)) {
00821                 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize);
00822 #ifdef LARGE_SMB_OFF_T
00823                 allocation_size |= (((SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize + 4)) << 32);
00824 #endif
00825                 if (allocation_size && (allocation_size > (SMB_BIG_UINT)file_len)) {
00826                         fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
00827                         if (fsp->is_directory) {
00828                                 close_file(fsp,ERROR_CLOSE);
00829                                 END_PROFILE(SMBntcreateX);
00830                                 /* Can't set allocation size on a directory. */
00831                                 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
00832                         }
00833                         if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
00834                                 close_file(fsp,ERROR_CLOSE);
00835                                 END_PROFILE(SMBntcreateX);
00836                                 return ERROR_NT(NT_STATUS_DISK_FULL);
00837                         }
00838                 } else {
00839                         fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)file_len);
00840                 }
00841         }
00842 
00843         /* 
00844          * If the caller set the extended oplock request bit
00845          * and we granted one (by whatever means) - set the
00846          * correct bit for extended oplock reply.
00847          */
00848 
00849         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
00850                 extended_oplock_granted = True;
00851         }
00852 
00853         if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
00854                 extended_oplock_granted = True;
00855         }
00856 
00857         if (flags & EXTENDED_RESPONSE_REQUIRED) {
00858                 /* This is very strange. We
00859                  * return 50 words, but only set
00860                  * the wcnt to 42 ? It's definately
00861                  * what happens on the wire....
00862                  */
00863                 set_message(outbuf,50,0,True);
00864                 SCVAL(outbuf,smb_wct,42);
00865         } else {
00866                 set_message(outbuf,34,0,True);
00867         }
00868 
00869         p = outbuf + smb_vwv2;
00870         
00871         /*
00872          * Currently as we don't support level II oplocks we just report
00873          * exclusive & batch here.
00874          */
00875 
00876         if (extended_oplock_granted) {
00877                 if (flags & REQUEST_BATCH_OPLOCK) {
00878                         SCVAL(p,0, BATCH_OPLOCK_RETURN);
00879                 } else {
00880                         SCVAL(p,0, EXCLUSIVE_OPLOCK_RETURN);
00881                 }
00882         } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
00883                 SCVAL(p,0, LEVEL_II_OPLOCK_RETURN);
00884         } else {
00885                 SCVAL(p,0,NO_OPLOCK_RETURN);
00886         }
00887         
00888         p++;
00889         SSVAL(p,0,fsp->fnum);
00890         p += 2;
00891         if ((create_disposition == FILE_SUPERSEDE) && (info == FILE_WAS_OVERWRITTEN)) {
00892                 SIVAL(p,0,FILE_WAS_SUPERSEDED);
00893         } else {
00894                 SIVAL(p,0,info);
00895         }
00896         p += 4;
00897 
00898         /* Create time. */
00899         c_timespec = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
00900         a_timespec = get_atimespec(&sbuf);
00901         m_timespec = get_mtimespec(&sbuf);
00902 
00903         if (lp_dos_filetime_resolution(SNUM(conn))) {
00904                 dos_filetime_timespec(&c_timespec);
00905                 dos_filetime_timespec(&a_timespec);
00906                 dos_filetime_timespec(&m_timespec);
00907         }
00908 
00909         put_long_date_timespec(p, c_timespec); /* create time. */
00910         p += 8;
00911         put_long_date_timespec(p, a_timespec); /* access time */
00912         p += 8;
00913         put_long_date_timespec(p, m_timespec); /* write time */
00914         p += 8;
00915         put_long_date_timespec(p, m_timespec); /* change time */
00916         p += 8;
00917         SIVAL(p,0,fattr); /* File Attributes. */
00918         p += 4;
00919         SOFF_T(p, 0, get_allocation_size(conn,fsp,&sbuf));
00920         p += 8;
00921         SOFF_T(p,0,file_len);
00922         p += 8;
00923         if (flags & EXTENDED_RESPONSE_REQUIRED) {
00924                 SSVAL(p,2,0x7);
00925         }
00926         p += 4;
00927         SCVAL(p,0,fsp->is_directory ? 1 : 0);
00928 
00929         if (flags & EXTENDED_RESPONSE_REQUIRED) {
00930                 uint32 perms = 0;
00931                 p += 25;
00932                 if (fsp->is_directory || can_write_to_file(conn, fname, &sbuf)) {
00933                         perms = FILE_GENERIC_ALL;
00934                 } else {
00935                         perms = FILE_GENERIC_READ|FILE_EXECUTE;
00936                 }
00937                 SIVAL(p,0,perms);
00938         }
00939 
00940         DEBUG(5,("reply_ntcreate_and_X: fnum = %d, open name = %s\n", fsp->fnum, fsp->fsp_name));
00941 
00942         result = chain_reply(inbuf,outbuf,length,bufsize);
00943         END_PROFILE(SMBntcreateX);
00944         return result;
00945 }
00946 
00947 /****************************************************************************
00948  Reply to a NT_TRANSACT_CREATE call to open a pipe.
00949 ****************************************************************************/
00950 
00951 static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
00952                                   uint16 **ppsetup, uint32 setup_count,
00953                                   char **ppparams, uint32 parameter_count,
00954                                   char **ppdata, uint32 data_count)
00955 {
00956         pstring fname;
00957         char *params = *ppparams;
00958         int ret;
00959         int pnum = -1;
00960         char *p = NULL;
00961         NTSTATUS status;
00962         size_t param_len;
00963         uint32 flags;
00964 
00965         /*
00966          * Ensure minimum number of parameters sent.
00967          */
00968 
00969         if(parameter_count < 54) {
00970                 DEBUG(0,("do_nt_transact_create_pipe - insufficient parameters (%u)\n", (unsigned int)parameter_count));
00971                 return ERROR_DOS(ERRDOS,ERRnoaccess);
00972         }
00973 
00974         flags = IVAL(params,0);
00975 
00976         srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status);
00977         if (!NT_STATUS_IS_OK(status)) {
00978                 return ERROR_NT(status);
00979         }
00980 
00981         if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0) {
00982                 return ret;
00983         }
00984         
00985         /* Realloc the size of parameters and data we will return */
00986         if (flags & EXTENDED_RESPONSE_REQUIRED) {
00987                 /* Extended response is 32 more byyes. */
00988                 param_len = 101;
00989         } else {
00990                 param_len = 69;
00991         }
00992         params = nttrans_realloc(ppparams, param_len);
00993         if(params == NULL) {
00994                 return ERROR_DOS(ERRDOS,ERRnomem);
00995         }
00996         
00997         p = params;
00998         SCVAL(p,0,NO_OPLOCK_RETURN);
00999         
01000         p += 2;
01001         SSVAL(p,0,pnum);
01002         p += 2;
01003         SIVAL(p,0,FILE_WAS_OPENED);
01004         p += 8;
01005         
01006         p += 32;
01007         SIVAL(p,0,FILE_ATTRIBUTE_NORMAL); /* File Attributes. */
01008         p += 20;
01009         /* File type. */
01010         SSVAL(p,0,FILE_TYPE_MESSAGE_MODE_PIPE);
01011         /* Device state. */
01012         SSVAL(p,2, 0x5FF); /* ? */
01013         p += 4;
01014         
01015         if (flags & EXTENDED_RESPONSE_REQUIRED) {
01016                 p += 25;
01017                 SIVAL(p,0,FILE_GENERIC_ALL);
01018                 /* 
01019                  * For pipes W2K3 seems to return
01020                  * 0x12019B next.
01021                  * This is ((FILE_GENERIC_READ|FILE_GENERIC_WRITE) & ~FILE_APPEND_DATA)
01022                  */
01023                 SIVAL(p,4,(FILE_GENERIC_READ|FILE_GENERIC_WRITE)&~FILE_APPEND_DATA);
01024         }
01025 
01026         DEBUG(5,("do_nt_transact_create_pipe: open name = %s\n", fname));
01027         
01028         /* Send the required number of replies */
01029         send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, param_len, *ppdata, 0);
01030         
01031         return -1;
01032 }
01033 
01034 /****************************************************************************
01035  Internal fn to set security descriptors.
01036 ****************************************************************************/
01037 
01038 static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 security_info_sent)
01039 {
01040         prs_struct pd;
01041         SEC_DESC *psd = NULL;
01042         TALLOC_CTX *mem_ctx;
01043         BOOL ret;
01044         
01045         if (sd_len == 0 || !lp_nt_acl_support(SNUM(fsp->conn))) {
01046                 return NT_STATUS_OK;
01047         }
01048 
01049         /*
01050          * Init the parse struct we will unmarshall from.
01051          */
01052 
01053         if ((mem_ctx = talloc_init("set_sd")) == NULL) {
01054                 DEBUG(0,("set_sd: talloc_init failed.\n"));
01055                 return NT_STATUS_NO_MEMORY;
01056         }
01057 
01058         prs_init(&pd, 0, mem_ctx, UNMARSHALL);
01059 
01060         /*
01061          * Setup the prs_struct to point at the memory we just
01062          * allocated.
01063          */
01064         
01065         prs_give_memory( &pd, data, sd_len, False);
01066 
01067         /*
01068          * Finally, unmarshall from the data buffer.
01069          */
01070 
01071         if(!sec_io_desc( "sd data", &psd, &pd, 1)) {
01072                 DEBUG(0,("set_sd: Error in unmarshalling security descriptor.\n"));
01073                 /*
01074                  * Return access denied for want of a better error message..
01075                  */ 
01076                 talloc_destroy(mem_ctx);
01077                 return NT_STATUS_NO_MEMORY;
01078         }
01079         
01080         if (psd->owner_sid==0) {
01081                 security_info_sent &= ~OWNER_SECURITY_INFORMATION;
01082         }
01083         if (psd->group_sid==0) {
01084                 security_info_sent &= ~GROUP_SECURITY_INFORMATION;
01085         }
01086         if (psd->sacl==0) {
01087                 security_info_sent &= ~SACL_SECURITY_INFORMATION;
01088         }
01089         if (psd->dacl==0) {
01090                 security_info_sent &= ~DACL_SECURITY_INFORMATION;
01091         }
01092         
01093         ret = SMB_VFS_FSET_NT_ACL( fsp, fsp->fh->fd, security_info_sent, psd);
01094         
01095         if (!ret) {
01096                 talloc_destroy(mem_ctx);
01097                 return NT_STATUS_ACCESS_DENIED;
01098         }
01099         
01100         talloc_destroy(mem_ctx);
01101         
01102         return NT_STATUS_OK;
01103 }
01104 
01105 /****************************************************************************
01106  Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
01107 ****************************************************************************/
01108                                                                                                                              
01109 static struct ea_list *read_nttrans_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
01110 {
01111         struct ea_list *ea_list_head = NULL;
01112         size_t offset = 0;
01113 
01114         if (data_size < 4) {
01115                 return NULL;
01116         }
01117 
01118         while (offset + 4 <= data_size) {
01119                 size_t next_offset = IVAL(pdata,offset);
01120                 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset + 4, data_size - offset - 4, NULL);
01121 
01122                 if (!eal) {
01123                         return NULL;
01124                 }
01125 
01126                 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
01127                 if (next_offset == 0) {
01128                         break;
01129                 }
01130                 offset += next_offset;
01131         }
01132                                                                                                                              
01133         return ea_list_head;
01134 }
01135 
01136 /****************************************************************************
01137  Reply to a NT_TRANSACT_CREATE call (needs to process SD's).
01138 ****************************************************************************/
01139 
01140 static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
01141                                   uint16 **ppsetup, uint32 setup_count,
01142                                   char **ppparams, uint32 parameter_count,
01143                                   char **ppdata, uint32 data_count, uint32 max_data_count)
01144 {
01145         pstring fname;
01146         char *params = *ppparams;
01147         char *data = *ppdata;
01148         /* Breakout the oplock request bits so we can set the reply bits separately. */
01149         int oplock_request = 0;
01150         uint32 fattr=0;
01151         SMB_OFF_T file_len = 0;
01152         SMB_STRUCT_STAT sbuf;
01153         int info = 0;
01154         files_struct *fsp = NULL;
01155         char *p = NULL;
01156         BOOL extended_oplock_granted = False;
01157         uint32 flags;
01158         uint32 access_mask;
01159         uint32 file_attributes;
01160         uint32 new_file_attributes;
01161         uint32 share_access;
01162         uint32 create_disposition;
01163         uint32 create_options;
01164         uint32 sd_len;
01165         uint32 ea_len;
01166         uint16 root_dir_fid;
01167         struct timespec c_timespec;
01168         struct timespec a_timespec;
01169         struct timespec m_timespec;
01170         struct ea_list *ea_list = NULL;
01171         TALLOC_CTX *ctx = NULL;
01172         char *pdata = NULL;
01173         NTSTATUS status;
01174         size_t param_len;
01175 
01176         DEBUG(5,("call_nt_transact_create\n"));
01177 
01178         /*
01179          * If it's an IPC, use the pipe handler.
01180          */
01181 
01182         if (IS_IPC(conn)) {
01183                 if (lp_nt_pipe_support()) {
01184                         return do_nt_transact_create_pipe(conn, inbuf, outbuf, length, 
01185                                         bufsize,
01186                                         ppsetup, setup_count,
01187                                         ppparams, parameter_count,
01188                                         ppdata, data_count);
01189                 } else {
01190                         return ERROR_DOS(ERRDOS,ERRnoaccess);
01191                 }
01192         }
01193 
01194         /*
01195          * Ensure minimum number of parameters sent.
01196          */
01197 
01198         if(parameter_count < 54) {
01199                 DEBUG(0,("call_nt_transact_create - insufficient parameters (%u)\n", (unsigned int)parameter_count));
01200                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
01201         }
01202 
01203         flags = IVAL(params,0);
01204         access_mask = IVAL(params,8);
01205         file_attributes = IVAL(params,20);
01206         share_access = IVAL(params,24);
01207         create_disposition = IVAL(params,28);
01208         create_options = IVAL(params,32);
01209         sd_len = IVAL(params,36);
01210         ea_len = IVAL(params,40);
01211         root_dir_fid = (uint16)IVAL(params,4);
01212 
01213         /* Ensure the data_len is correct for the sd and ea values given. */
01214         if ((ea_len + sd_len > data_count) ||
01215                         (ea_len > data_count) || (sd_len > data_count) ||
01216                         (ea_len + sd_len < ea_len) || (ea_len + sd_len < sd_len)) {
01217                 DEBUG(10,("call_nt_transact_create - ea_len = %u, sd_len = %u, data_count = %u\n",
01218                         (unsigned int)ea_len, (unsigned int)sd_len, (unsigned int)data_count ));
01219                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
01220         }
01221 
01222         if (ea_len) {
01223                 if (!lp_ea_support(SNUM(conn))) {
01224                         DEBUG(10,("call_nt_transact_create - ea_len = %u but EA's not supported.\n",
01225                                 (unsigned int)ea_len ));
01226                         return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
01227                 }
01228 
01229                 if (ea_len < 10) {
01230                         DEBUG(10,("call_nt_transact_create - ea_len = %u - too small (should be more than 10)\n",
01231                                 (unsigned int)ea_len ));
01232                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
01233                 }
01234         }
01235 
01236         if (create_options & FILE_OPEN_BY_FILE_ID) {
01237                 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
01238         }
01239 
01240         /*
01241          * Get the file name.
01242          */
01243 
01244         if(root_dir_fid != 0) {
01245                 /*
01246                  * This filename is relative to a directory fid.
01247                  */
01248                 files_struct *dir_fsp = file_fsp(params,4);
01249 
01250                 if(!dir_fsp) {
01251                         return ERROR_DOS(ERRDOS,ERRbadfid);
01252                 }
01253 
01254                 if(!dir_fsp->is_directory) {
01255                         srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status);
01256                         if (!NT_STATUS_IS_OK(status)) {
01257                                 return ERROR_NT(status);
01258                         }
01259 
01260                         /*
01261                          * Check to see if this is a mac fork of some kind.
01262                          */
01263 
01264                         if( is_ntfs_stream_name(fname)) {
01265                                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
01266                         }
01267 
01268                         return ERROR_DOS(ERRDOS,ERRbadfid);
01269                 }
01270 
01271                 /*
01272                  * Copy in the base directory name.
01273                  */
01274 
01275                 pstrcpy( fname, dir_fsp->fsp_name );
01276 
01277                 if (ISDOT(fname)) {
01278                         fname[0] = '\0';
01279                 } else {
01280                         size_t dir_name_len = strlen(fname);
01281                         /*
01282                          * Ensure it ends in a '\'.
01283                          */
01284 
01285                         if((fname[dir_name_len-1] != '\\') && (fname[dir_name_len-1] != '/')) {
01286                                 pstrcat(fname, "/");
01287                         }
01288                 }
01289 
01290                 {
01291                         pstring tmpname;
01292                         srvstr_get_path(inbuf, tmpname, params+53, sizeof(tmpname), parameter_count-53, STR_TERMINATE, &status);
01293                         if (!NT_STATUS_IS_OK(status)) {
01294                                 return ERROR_NT(status);
01295                         }
01296                         pstrcat(fname, tmpname);
01297                 }
01298         } else {
01299                 srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status);
01300                 if (!NT_STATUS_IS_OK(status)) {
01301                         return ERROR_NT(status);
01302                 }
01303 
01304                 /*
01305                  * Check to see if this is a mac fork of some kind.
01306                  */
01307 
01308                 if( is_ntfs_stream_name(fname)) {
01309                         return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
01310                 }
01311         }
01312 
01313         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
01314         if (oplock_request) {
01315                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
01316         }
01317 
01318         /*
01319          * Ordinary file or directory.
01320          */
01321                 
01322         /*
01323          * Check if POSIX semantics are wanted.
01324          */
01325                 
01326         new_file_attributes = set_posix_case_semantics(conn, file_attributes);
01327     
01328         status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
01329         if (!NT_STATUS_IS_OK(status)) {
01330                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
01331                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
01332                 }
01333                 return ERROR_NT(status);
01334         }
01335 
01336         status = unix_convert(conn, fname, False, NULL, &sbuf);
01337         if (!NT_STATUS_IS_OK(status)) {
01338                 restore_case_semantics(conn, file_attributes);
01339                 return ERROR_NT(status);
01340         }
01341         /* All file access must go through check_name() */
01342         status = check_name(conn, fname);
01343         if (!NT_STATUS_IS_OK(status)) {
01344                 restore_case_semantics(conn, file_attributes);
01345                 return ERROR_NT(status);
01346         }
01347 
01348         /* This is the correct thing to do (check every time) but can_delete is
01349            expensive (it may have to read the parent directory permissions). So
01350            for now we're not doing it unless we have a strong hint the client
01351            is really going to delete this file. If the client is forcing FILE_CREATE
01352            let the filesystem take care of the permissions. */
01353 
01354         /* Setting FILE_SHARE_DELETE is the hint. */
01355 
01356         if (lp_acl_check_permissions(SNUM(conn))
01357             && (create_disposition != FILE_CREATE)
01358             && (share_access & FILE_SHARE_DELETE)
01359             && (access_mask & DELETE_ACCESS)) {
01360                 if ((dos_mode(conn, fname, &sbuf) & FILE_ATTRIBUTE_READONLY) ||
01361                                 !can_delete_file_in_directory(conn, fname)) {
01362                         restore_case_semantics(conn, file_attributes);
01363                         return ERROR_NT(NT_STATUS_ACCESS_DENIED);
01364                 }
01365         }
01366 
01367         if (ea_len) {
01368                 pdata = data + sd_len;
01369 
01370                 /* We have already checked that ea_len <= data_count here. */
01371                 ea_list = read_nttrans_ea_list(tmp_talloc_ctx(), pdata,
01372                                                ea_len);
01373                 if (!ea_list ) {
01374                         restore_case_semantics(conn, file_attributes);
01375                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
01376                 }
01377         }
01378 
01379         /*
01380          * If it's a request for a directory open, deal with it separately.
01381          */
01382 
01383         if(create_options & FILE_DIRECTORY_FILE) {
01384 
01385                 /* Can't open a temp directory. IFS kit test. */
01386                 if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) {
01387                         restore_case_semantics(conn, file_attributes);
01388                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
01389                 }
01390 
01391                 /*
01392                  * We will get a create directory here if the Win32
01393                  * app specified a security descriptor in the 
01394                  * CreateDirectory() call.
01395                  */
01396 
01397                 oplock_request = 0;
01398                 status = open_directory(conn, fname, &sbuf,
01399                                         access_mask,
01400                                         share_access,
01401                                         create_disposition,
01402                                         create_options,
01403                                         new_file_attributes,
01404                                         &info, &fsp);
01405         } else {
01406 
01407                 /*
01408                  * Ordinary file case.
01409                  */
01410 
01411                 status = open_file_ntcreate(conn,fname,&sbuf,
01412                                         access_mask,
01413                                         share_access,
01414                                         create_disposition,
01415                                         create_options,
01416                                         new_file_attributes,
01417                                         oplock_request,
01418                                         &info, &fsp);
01419 
01420                 if (!NT_STATUS_IS_OK(status)) {
01421                         if (NT_STATUS_EQUAL(status,
01422                                             NT_STATUS_FILE_IS_A_DIRECTORY)) {
01423 
01424                                 /*
01425                                  * Fail the open if it was explicitly a non-directory file.
01426                                  */
01427 
01428                                 if (create_options & FILE_NON_DIRECTORY_FILE) {
01429                                         restore_case_semantics(conn, file_attributes);
01430                                         return ERROR_FORCE_NT(NT_STATUS_FILE_IS_A_DIRECTORY);
01431                                 }
01432 
01433                                 oplock_request = 0;
01434                                 status = open_directory(conn, fname, &sbuf,
01435                                                         access_mask,
01436                                                         share_access,
01437                                                         create_disposition,
01438                                                         create_options,
01439                                                         new_file_attributes,
01440                                                         &info, &fsp);
01441                         }
01442                 }
01443         }
01444 
01445         restore_case_semantics(conn, file_attributes);
01446         if(!NT_STATUS_IS_OK(status)) {
01447 
01448                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
01449                         /* We have re-scheduled this call. */
01450                         return -1;
01451                 }
01452 
01453                 return ERROR_OPEN(status);
01454         }
01455 
01456         /*
01457          * According to the MS documentation, the only time the security
01458          * descriptor is applied to the opened file is iff we *created* the
01459          * file; an existing file stays the same.
01460          *
01461          * Also, it seems (from observation) that you can open the file with
01462          * any access mask but you can still write the sd. We need to override
01463          * the granted access before we call set_sd
01464          * Patch for bug #2242 from Tom Lackemann <cessnatomny@yahoo.com>.
01465          */
01466 
01467         if (lp_nt_acl_support(SNUM(conn)) && sd_len && info == FILE_WAS_CREATED) {
01468                 uint32 saved_access_mask = fsp->access_mask;
01469 
01470                 /* We have already checked that sd_len <= data_count here. */
01471 
01472                 fsp->access_mask = FILE_GENERIC_ALL;
01473 
01474                 status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION);
01475                 if (!NT_STATUS_IS_OK(status)) {
01476                         talloc_destroy(ctx);
01477                         close_file(fsp,ERROR_CLOSE);
01478                         restore_case_semantics(conn, file_attributes);
01479                         return ERROR_NT(status);
01480                 }
01481                 fsp->access_mask = saved_access_mask;
01482         }
01483         
01484         if (ea_len && (info == FILE_WAS_CREATED)) {
01485                 status = set_ea(conn, fsp, fname, ea_list);
01486                 if (!NT_STATUS_IS_OK(status)) {
01487                         close_file(fsp,ERROR_CLOSE);
01488                         restore_case_semantics(conn, file_attributes);
01489                         return ERROR_NT(status);
01490                 }
01491         }
01492 
01493         restore_case_semantics(conn, file_attributes);
01494 
01495         file_len = sbuf.st_size;
01496         fattr = dos_mode(conn,fname,&sbuf);
01497         if(fattr == 0) {
01498                 fattr = FILE_ATTRIBUTE_NORMAL;
01499         }
01500         if (!fsp->is_directory && (fattr & aDIR)) {
01501                 close_file(fsp,ERROR_CLOSE);
01502                 return ERROR_DOS(ERRDOS,ERRnoaccess);
01503         } 
01504         
01505         /* Save the requested allocation size. */
01506         if ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN)) {
01507                 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(params,12);
01508 #ifdef LARGE_SMB_OFF_T
01509                 allocation_size |= (((SMB_BIG_UINT)IVAL(params,16)) << 32);
01510 #endif
01511                 if (allocation_size && (allocation_size > file_len)) {
01512                         fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
01513                         if (fsp->is_directory) {
01514                                 close_file(fsp,ERROR_CLOSE);
01515                                 /* Can't set allocation size on a directory. */
01516                                 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
01517                         }
01518                         if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
01519                                 close_file(fsp,ERROR_CLOSE);
01520                                 return ERROR_NT(NT_STATUS_DISK_FULL);
01521                         }
01522                 } else {
01523                         fsp->initial_allocation_size = smb_roundup(fsp->conn, (SMB_BIG_UINT)file_len);
01524                 }
01525         }
01526 
01527         /* 
01528          * If the caller set the extended oplock request bit
01529          * and we granted one (by whatever means) - set the
01530          * correct bit for extended oplock reply.
01531          */
01532 
01533         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
01534                 extended_oplock_granted = True;
01535         }
01536 
01537         if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
01538                 extended_oplock_granted = True;
01539         }
01540 
01541         /* Realloc the size of parameters and data we will return */
01542         if (flags & EXTENDED_RESPONSE_REQUIRED) {
01543                 /* Extended response is 32 more byyes. */
01544                 param_len = 101;
01545         } else {
01546                 param_len = 69;
01547         }
01548         params = nttrans_realloc(ppparams, param_len);
01549         if(params == NULL) {
01550                 return ERROR_DOS(ERRDOS,ERRnomem);
01551         }
01552 
01553         p = params;
01554         if (extended_oplock_granted) {
01555                 if (flags & REQUEST_BATCH_OPLOCK) {
01556                         SCVAL(p,0, BATCH_OPLOCK_RETURN);
01557                 } else {
01558                         SCVAL(p,0, EXCLUSIVE_OPLOCK_RETURN);
01559                 }
01560         } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
01561                 SCVAL(p,0, LEVEL_II_OPLOCK_RETURN);
01562         } else {
01563                 SCVAL(p,0,NO_OPLOCK_RETURN);
01564         }
01565         
01566         p += 2;
01567         SSVAL(p,0,fsp->fnum);
01568         p += 2;
01569         if ((create_disposition == FILE_SUPERSEDE) && (info == FILE_WAS_OVERWRITTEN)) {
01570                 SIVAL(p,0,FILE_WAS_SUPERSEDED);
01571         } else {
01572                 SIVAL(p,0,info);
01573         }
01574         p += 8;
01575 
01576         /* Create time. */
01577         c_timespec = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
01578         a_timespec = get_atimespec(&sbuf);
01579         m_timespec = get_mtimespec(&sbuf);
01580 
01581         if (lp_dos_filetime_resolution(SNUM(conn))) {
01582                 dos_filetime_timespec(&c_timespec);
01583                 dos_filetime_timespec(&a_timespec);
01584                 dos_filetime_timespec(&m_timespec);
01585         }
01586 
01587         put_long_date_timespec(p, c_timespec); /* create time. */
01588         p += 8;
01589         put_long_date_timespec(p, a_timespec); /* access time */
01590         p += 8;
01591         put_long_date_timespec(p, m_timespec); /* write time */
01592         p += 8;
01593         put_long_date_timespec(p, m_timespec); /* change time */
01594         p += 8;
01595         SIVAL(p,0,fattr); /* File Attributes. */
01596         p += 4;
01597         SOFF_T(p, 0, get_allocation_size(conn,fsp,&sbuf));
01598         p += 8;
01599         SOFF_T(p,0,file_len);
01600         p += 8;
01601         if (flags & EXTENDED_RESPONSE_REQUIRED) {
01602                 SSVAL(p,2,0x7);
01603         }
01604         p += 4;
01605         SCVAL(p,0,fsp->is_directory ? 1 : 0);
01606 
01607         if (flags & EXTENDED_RESPONSE_REQUIRED) {
01608                 uint32 perms = 0;
01609                 p += 25;
01610                 if (fsp->is_directory || can_write_to_file(conn, fname, &sbuf)) {
01611                         perms = FILE_GENERIC_ALL;
01612                 } else {
01613                         perms = FILE_GENERIC_READ|FILE_EXECUTE;
01614                 }
01615                 SIVAL(p,0,perms);
01616         }
01617 
01618         DEBUG(5,("call_nt_transact_create: open name = %s\n", fname));
01619 
01620         /* Send the required number of replies */
01621         send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, param_len, *ppdata, 0);
01622 
01623         return -1;
01624 }
01625 
01626 /****************************************************************************
01627  Reply to a NT CANCEL request.
01628  conn POINTER CAN BE NULL HERE !
01629 ****************************************************************************/
01630 
01631 int reply_ntcancel(connection_struct *conn,
01632                    char *inbuf,char *outbuf,int length,int bufsize)
01633 {
01634         /*
01635          * Go through and cancel any pending change notifies.
01636          */
01637         
01638         int mid = SVAL(inbuf,smb_mid);
01639         START_PROFILE(SMBntcancel);
01640         remove_pending_change_notify_requests_by_mid(mid);
01641         remove_pending_lock_requests_by_mid(mid);
01642         srv_cancel_sign_response(mid);
01643         
01644         DEBUG(3,("reply_ntcancel: cancel called on mid = %d.\n", mid));
01645 
01646         END_PROFILE(SMBntcancel);
01647         return(-1);
01648 }
01649 
01650 /****************************************************************************
01651  Copy a file.
01652 ****************************************************************************/
01653 
01654 static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *newname, uint32 attrs)
01655 {
01656         SMB_STRUCT_STAT sbuf1, sbuf2;
01657         pstring last_component_oldname;
01658         pstring last_component_newname;
01659         files_struct *fsp1,*fsp2;
01660         uint32 fattr;
01661         int info;
01662         SMB_OFF_T ret=-1;
01663         NTSTATUS status = NT_STATUS_OK;
01664 
01665         ZERO_STRUCT(sbuf1);
01666         ZERO_STRUCT(sbuf2);
01667 
01668         if (!CAN_WRITE(conn)) {
01669                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
01670         }
01671 
01672         status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
01673         if (!NT_STATUS_IS_OK(status)) {
01674                 return status;
01675         }
01676 
01677         status = check_name(conn, oldname);
01678         if (!NT_STATUS_IS_OK(status)) {
01679                 return status;
01680         }
01681 
01682         /* Source must already exist. */
01683         if (!VALID_STAT(sbuf1)) {
01684                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
01685         }
01686         /* Ensure attributes match. */
01687         fattr = dos_mode(conn,oldname,&sbuf1);
01688         if ((fattr & ~attrs) & (aHIDDEN | aSYSTEM)) {
01689                 return NT_STATUS_NO_SUCH_FILE;
01690         }
01691 
01692         status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
01693         if (!NT_STATUS_IS_OK(status)) {
01694                 return status;
01695         }
01696 
01697         status = check_name(conn, newname);
01698         if (!NT_STATUS_IS_OK(status)) {
01699                 return status;
01700         }
01701 
01702         /* Disallow if newname already exists. */
01703         if (VALID_STAT(sbuf2)) {
01704                 return NT_STATUS_OBJECT_NAME_COLLISION;
01705         }
01706 
01707         /* No links from a directory. */
01708         if (S_ISDIR(sbuf1.st_mode)) {
01709                 return NT_STATUS_FILE_IS_A_DIRECTORY;
01710         }
01711 
01712         /* Ensure this is within the share. */
01713         status = reduce_name(conn, oldname);
01714         if (!NT_STATUS_IS_OK(status)) {
01715                 return status;
01716         }
01717 
01718         DEBUG(10,("copy_internals: doing file copy %s to %s\n", oldname, newname));
01719 
01720         status = open_file_ntcreate(conn,oldname,&sbuf1,
01721                         FILE_READ_DATA, /* Read-only. */
01722                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
01723                         FILE_OPEN,
01724                         0, /* No create options. */
01725                         FILE_ATTRIBUTE_NORMAL,
01726                         NO_OPLOCK,
01727                         &info, &fsp1);
01728 
01729         if (!NT_STATUS_IS_OK(status)) {
01730                 return status;
01731         }
01732 
01733         status = open_file_ntcreate(conn,newname,&sbuf2,
01734                         FILE_WRITE_DATA, /* Read-only. */
01735                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
01736                         FILE_CREATE,
01737                         0, /* No create options. */
01738                         fattr,
01739                         NO_OPLOCK,
01740                         &info, &fsp2);
01741 
01742         if (!NT_STATUS_IS_OK(status)) {
01743                 close_file(fsp1,ERROR_CLOSE);
01744                 return status;
01745         }
01746 
01747         if (sbuf1.st_size) {
01748                 ret = vfs_transfer_file(fsp1, fsp2, sbuf1.st_size);
01749         }
01750 
01751         /*
01752          * As we are opening fsp1 read-only we only expect
01753          * an error on close on fsp2 if we are out of space.
01754          * Thus we don't look at the error return from the
01755          * close of fsp1.
01756          */
01757         close_file(fsp1,NORMAL_CLOSE);
01758 
01759         /* Ensure the modtime is set correctly on the destination file. */
01760         fsp_set_pending_modtime(fsp2, get_mtimespec(&sbuf1));
01761 
01762         status = close_file(fsp2,NORMAL_CLOSE);
01763 
01764         /* Grrr. We have to do this as open_file_ntcreate adds aARCH when it
01765            creates the file. This isn't the correct thing to do in the copy
01766            case. JRA */
01767         file_set_dosmode(conn, newname, fattr, &sbuf2,
01768                          parent_dirname(newname));
01769 
01770         if (ret < (SMB_OFF_T)sbuf1.st_size) {
01771                 return NT_STATUS_DISK_FULL;
01772         }
01773 
01774         if (!NT_STATUS_IS_OK(status)) {
01775                 DEBUG(3,("copy_internals: Error %s copy file %s to %s\n",
01776                         nt_errstr(status), oldname, newname));
01777         }
01778         return status;
01779 }
01780 
01781 /****************************************************************************
01782  Reply to a NT rename request.
01783 ****************************************************************************/
01784 
01785 int reply_ntrename(connection_struct *conn,
01786                    char *inbuf,char *outbuf,int length,int bufsize)
01787 {
01788         int outsize = 0;
01789         pstring oldname;
01790         pstring newname;
01791         char *p;
01792         NTSTATUS status;
01793         BOOL src_has_wcard = False;
01794         BOOL dest_has_wcard = False;
01795         uint32 attrs = SVAL(inbuf,smb_vwv0);
01796         uint16 rename_type = SVAL(inbuf,smb_vwv1);
01797 
01798         START_PROFILE(SMBntrename);
01799 
01800         p = smb_buf(inbuf) + 1;
01801         p += srvstr_get_path_wcard(inbuf, oldname, p, sizeof(oldname), 0, STR_TERMINATE, &status, &src_has_wcard);
01802         if (!NT_STATUS_IS_OK(status)) {
01803                 END_PROFILE(SMBntrename);
01804                 return ERROR_NT(status);
01805         }
01806 
01807         if( is_ntfs_stream_name(oldname)) {
01808                 /* Can't rename a stream. */
01809                 END_PROFILE(SMBntrename);
01810                 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
01811         }
01812 
01813         if (ms_has_wild(oldname)) {
01814                 END_PROFILE(SMBntrename);
01815                 return ERROR_NT(NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
01816         }
01817 
01818         p++;
01819         p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wcard);
01820         if (!NT_STATUS_IS_OK(status)) {
01821                 END_PROFILE(SMBntrename);
01822                 return ERROR_NT(status);
01823         }
01824         
01825         status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
01826         if (!NT_STATUS_IS_OK(status)) {
01827                 END_PROFILE(SMBntrename);
01828                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
01829                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
01830                 }
01831                 return ERROR_NT(status);
01832         }
01833 
01834         status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname);
01835         if (!NT_STATUS_IS_OK(status)) {
01836                 END_PROFILE(SMBntrename);
01837                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
01838                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
01839                 }
01840                 return ERROR_NT(status);
01841         }
01842 
01843         DEBUG(3,("reply_ntrename : %s -> %s\n",oldname,newname));
01844         
01845         switch(rename_type) {
01846                 case RENAME_FLAG_RENAME:
01847                         status = rename_internals(conn, oldname, newname, attrs, False, src_has_wcard, dest_has_wcard);
01848                         break;
01849                 case RENAME_FLAG_HARD_LINK:
01850                         if (src_has_wcard || dest_has_wcard) {
01851                                 /* No wildcards. */
01852                                 status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
01853                         } else {
01854                                 status = hardlink_internals(conn, oldname, newname);
01855                         }
01856                         break;
01857                 case RENAME_FLAG_COPY:
01858                         if (src_has_wcard || dest_has_wcard) {
01859                                 /* No wildcards. */
01860                                 status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
01861                         } else {
01862                                 status = copy_internals(conn, oldname, newname, attrs);
01863                         }
01864                         break;
01865                 case RENAME_FLAG_MOVE_CLUSTER_INFORMATION:
01866                         status = NT_STATUS_INVALID_PARAMETER;
01867                         break;
01868                 default:
01869                         status = NT_STATUS_ACCESS_DENIED; /* Default error. */
01870                         break;
01871         }
01872 
01873         if (!NT_STATUS_IS_OK(status)) {
01874                 END_PROFILE(SMBntrename);
01875                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
01876                         /* We have re-scheduled this call. */
01877                         return -1;
01878                 }
01879                 return ERROR_NT(status);
01880         }
01881 
01882         outsize = set_message(outbuf,0,0,False);
01883   
01884         END_PROFILE(SMBntrename);
01885         return(outsize);
01886 }
01887 
01888 /****************************************************************************
01889  Reply to a notify change - queue the request and 
01890  don't allow a directory to be opened.
01891 ****************************************************************************/
01892 
01893 static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf,
01894                                           char *outbuf, int length,
01895                                           int bufsize, 
01896                                           uint16 **ppsetup, uint32 setup_count,
01897                                           char **ppparams,
01898                                           uint32 parameter_count,
01899                                           char **ppdata, uint32 data_count,
01900                                           uint32 max_data_count,
01901                                           uint32 max_param_count)
01902 {
01903         uint16 *setup = *ppsetup;
01904         files_struct *fsp;
01905         uint32 filter;
01906         NTSTATUS status;
01907         BOOL recursive;
01908 
01909         if(setup_count < 6) {
01910                 return ERROR_DOS(ERRDOS,ERRbadfunc);
01911         }
01912 
01913         fsp = file_fsp((char *)setup,4);
01914         filter = IVAL(setup, 0);
01915         recursive = (SVAL(setup, 6) != 0) ? True : False;
01916 
01917         DEBUG(3,("call_nt_transact_notify_change\n"));
01918 
01919         if(!fsp) {
01920                 return ERROR_DOS(ERRDOS,ERRbadfid);
01921         }
01922 
01923         {
01924                 char *filter_string;
01925 
01926                 if (!(filter_string = notify_filter_string(NULL, filter))) {
01927                         return ERROR_NT(NT_STATUS_NO_MEMORY);
01928                 }
01929 
01930                 DEBUG(3,("call_nt_transact_notify_change: notify change "
01931                          "called on %s, filter = %s, recursive = %d\n",
01932                          fsp->fsp_name, filter_string, recursive));
01933 
01934                 TALLOC_FREE(filter_string);
01935         }
01936 
01937         if((!fsp->is_directory) || (conn != fsp->conn)) {
01938                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
01939         }
01940 
01941         if (fsp->notify == NULL) {
01942 
01943                 status = change_notify_create(fsp, filter, recursive);
01944 
01945                 if (!NT_STATUS_IS_OK(status)) {
01946                         DEBUG(10, ("change_notify_create returned %s\n",
01947                                    nt_errstr(status)));
01948                         return ERROR_NT(status);
01949                 }
01950         }
01951 
01952         if (fsp->notify->num_changes != 0) {
01953 
01954                 /*
01955                  * We've got changes pending, respond immediately
01956                  */
01957 
01958                 /*
01959                  * TODO: write a torture test to check the filtering behaviour
01960                  * here.
01961                  */
01962 
01963                 change_notify_reply(inbuf, max_param_count, fsp->notify);
01964 
01965                 /*
01966                  * change_notify_reply() above has independently sent its
01967                  * results
01968                  */
01969                 return -1;
01970         }
01971 
01972         /*
01973          * No changes pending, queue the request
01974          */
01975 
01976         status = change_notify_add_request(inbuf, max_param_count, filter,
01977                         recursive, fsp);
01978         if (!NT_STATUS_IS_OK(status)) {
01979                 return ERROR_NT(status);
01980         }
01981 
01982         return -1;
01983 }
01984 
01985 /****************************************************************************
01986  Reply to an NT transact rename command.
01987 ****************************************************************************/
01988 
01989 static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
01990                                   uint16 **ppsetup, uint32 setup_count,
01991                                   char **ppparams, uint32 parameter_count,
01992                                   char **ppdata, uint32 data_count, uint32 max_data_count)
01993 {
01994         char *params = *ppparams;
01995         pstring new_name;
01996         files_struct *fsp = NULL;
01997         BOOL replace_if_exists = False;
01998         BOOL dest_has_wcard = False;
01999         NTSTATUS status;
02000 
02001         if(parameter_count < 5) {
02002                 return ERROR_DOS(ERRDOS,ERRbadfunc);
02003         }
02004 
02005         fsp = file_fsp(params, 0);
02006         replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False;
02007         CHECK_FSP(fsp, conn);
02008         srvstr_get_path_wcard(inbuf, new_name, params+4, sizeof(new_name), parameter_count - 4,
02009                         STR_TERMINATE, &status, &dest_has_wcard);
02010         if (!NT_STATUS_IS_OK(status)) {
02011                 return ERROR_NT(status);
02012         }
02013 
02014         status = rename_internals(conn, fsp->fsp_name,
02015                                   new_name, 0, replace_if_exists, False, dest_has_wcard);
02016 
02017         if (!NT_STATUS_IS_OK(status)) {
02018                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
02019                         /* We have re-scheduled this call. */
02020                         return -1;
02021                 }
02022                 return ERROR_NT(status);
02023         }
02024 
02025         /*
02026          * Rename was successful.
02027          */
02028         send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0);
02029         
02030         DEBUG(3,("nt transact rename from = %s, to = %s succeeded.\n", 
02031                  fsp->fsp_name, new_name));
02032         
02033         return -1;
02034 }
02035 
02036 /******************************************************************************
02037  Fake up a completely empty SD.
02038 *******************************************************************************/
02039 
02040 static size_t get_null_nt_acl(TALLOC_CTX *mem_ctx, SEC_DESC **ppsd)
02041 {
02042         size_t sd_size;
02043 
02044         *ppsd = make_standard_sec_desc( mem_ctx, &global_sid_World, &global_sid_World, NULL, &sd_size);
02045         if(!*ppsd) {
02046                 DEBUG(0,("get_null_nt_acl: Unable to malloc space for security descriptor.\n"));
02047                 sd_size = 0;
02048         }
02049 
02050         return sd_size;
02051 }
02052 
02053 /****************************************************************************
02054  Reply to query a security descriptor.
02055 ****************************************************************************/
02056 
02057 static int call_nt_transact_query_security_desc(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, 
02058                                   uint16 **ppsetup, uint32 setup_count,
02059                                   char **ppparams, uint32 parameter_count,
02060                                   char **ppdata, uint32 data_count, uint32 max_data_count)
02061 {
02062         char *params = *ppparams;
02063         char *data = *ppdata;
02064         prs_struct pd;
02065         SEC_DESC *psd = NULL;
02066         size_t sd_size;
02067         uint32 security_info_wanted;
02068         TALLOC_CTX *mem_ctx;
02069         files_struct *fsp = NULL;
02070 
02071         if(parameter_count < 8) {
02072                 return ERROR_DOS(ERRDOS,ERRbadfunc);
02073         }
02074 
02075         fsp = file_fsp(params,0);
02076         if(!fsp) {
02077                 return ERROR_DOS(ERRDOS,ERRbadfid);
02078         }
02079 
02080         security_info_wanted = IVAL(params,4);
02081 
02082         DEBUG(3,("call_nt_transact_query_security_desc: file = %s, info_wanted = 0x%x\n", fsp->fsp_name,
02083                         (unsigned int)security_info_wanted ));
02084 
02085         params = nttrans_realloc(ppparams, 4);
02086         if(params == NULL) {
02087                 return ERROR_DOS(ERRDOS,ERRnomem);
02088         }
02089 
02090         if ((mem_ctx = talloc_init("call_nt_transact_query_security_desc")) == NULL) {
02091                 DEBUG(0,("call_nt_transact_query_security_desc: talloc_init failed.\n"));
02092                 return ERROR_DOS(ERRDOS,ERRnomem);
02093         }
02094 
02095         /*
02096          * Get the permissions to return.
02097          */
02098 
02099         if (!lp_nt_acl_support(SNUM(conn))) {
02100                 sd_size = get_null_nt_acl(mem_ctx, &psd);
02101         } else {
02102                 sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd, security_info_wanted, &psd);
02103         }
02104 
02105         if (sd_size == 0) {
02106                 talloc_destroy(mem_ctx);
02107                 return(UNIXERROR(ERRDOS,ERRnoaccess));
02108         }
02109 
02110         DEBUG(3,("call_nt_transact_query_security_desc: sd_size = %lu.\n",(unsigned long)sd_size));
02111 
02112         SIVAL(params,0,(uint32)sd_size);
02113 
02114         if(max_data_count < sd_size) {
02115 
02116                 send_nt_replies(outbuf, bufsize, NT_STATUS_BUFFER_TOO_SMALL,
02117                                 params, 4, *ppdata, 0);
02118                 talloc_destroy(mem_ctx);
02119                 return -1;
02120         }
02121 
02122         /*
02123          * Allocate the data we will point this at.
02124          */
02125 
02126         data = nttrans_realloc(ppdata, sd_size);
02127         if(data == NULL) {
02128                 talloc_destroy(mem_ctx);
02129                 return ERROR_DOS(ERRDOS,ERRnomem);
02130         }
02131 
02132         /*
02133          * Init the parse struct we will marshall into.
02134          */
02135 
02136         prs_init(&pd, 0, mem_ctx, MARSHALL);
02137 
02138         /*
02139          * Setup the prs_struct to point at the memory we just
02140          * allocated.
02141          */
02142 
02143         prs_give_memory( &pd, data, (uint32)sd_size, False);
02144 
02145         /*
02146          * Finally, linearize into the outgoing buffer.
02147          */
02148 
02149         if(!sec_io_desc( "sd data", &psd, &pd, 1)) {
02150                 DEBUG(0,("call_nt_transact_query_security_desc: Error in marshalling \
02151 security descriptor.\n"));
02152                 /*
02153                  * Return access denied for want of a better error message..
02154                  */ 
02155                 talloc_destroy(mem_ctx);
02156                 return(UNIXERROR(ERRDOS,ERRnoaccess));
02157         }
02158 
02159         /*
02160          * Now we can delete the security descriptor.
02161          */
02162 
02163         talloc_destroy(mem_ctx);
02164 
02165         send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, 4, data,
02166                         (int)sd_size);
02167         return -1;
02168 }
02169 
02170 /****************************************************************************
02171  Reply to set a security descriptor. Map to UNIX perms or POSIX ACLs.
02172 ****************************************************************************/
02173 
02174 static int call_nt_transact_set_security_desc(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
02175                                   uint16 **ppsetup, uint32 setup_count,
02176                                   char **ppparams, uint32 parameter_count,
02177                                   char **ppdata, uint32 data_count, uint32 max_data_count)
02178 {
02179         char *params= *ppparams;
02180         char *data = *ppdata;
02181         files_struct *fsp = NULL;
02182         uint32 security_info_sent = 0;
02183         NTSTATUS nt_status;
02184 
02185         if(parameter_count < 8) {
02186                 return ERROR_DOS(ERRDOS,ERRbadfunc);
02187         }
02188 
02189         if((fsp = file_fsp(params,0)) == NULL) {
02190                 return ERROR_DOS(ERRDOS,ERRbadfid);
02191         }
02192 
02193         if(!lp_nt_acl_support(SNUM(conn))) {
02194                 goto done;
02195         }
02196 
02197         security_info_sent = IVAL(params,4);
02198 
02199         DEBUG(3,("call_nt_transact_set_security_desc: file = %s, sent 0x%x\n", fsp->fsp_name,
02200                 (unsigned int)security_info_sent ));
02201 
02202         if (data_count == 0) {
02203                 return ERROR_DOS(ERRDOS, ERRnoaccess);
02204         }
02205 
02206         if (!NT_STATUS_IS_OK(nt_status = set_sd( fsp, data, data_count, security_info_sent))) {
02207                 return ERROR_NT(nt_status);
02208         }
02209 
02210   done:
02211 
02212         send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0);
02213         return -1;
02214 }
02215    
02216 /****************************************************************************
02217  Reply to NT IOCTL
02218 ****************************************************************************/
02219 
02220 static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, 
02221                                   uint16 **ppsetup, uint32 setup_count,
02222                                   char **ppparams, uint32 parameter_count,
02223                                   char **ppdata, uint32 data_count, uint32 max_data_count)
02224 {
02225         uint32 function;
02226         uint16 fidnum;
02227         files_struct *fsp;
02228         uint8 isFSctl;
02229         uint8 compfilter;
02230         static BOOL logged_message;
02231         char *pdata = *ppdata;
02232 
02233         if (setup_count != 8) {
02234                 DEBUG(3,("call_nt_transact_ioctl: invalid setup count %d\n", setup_count));
02235                 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
02236         }
02237 
02238         function = IVAL(*ppsetup, 0);
02239         fidnum = SVAL(*ppsetup, 4);
02240         isFSctl = CVAL(*ppsetup, 6);
02241         compfilter = CVAL(*ppsetup, 7);
02242 
02243         DEBUG(10,("call_nt_transact_ioctl: function[0x%08X] FID[0x%04X] isFSctl[0x%02X] compfilter[0x%02X]\n", 
02244                  function, fidnum, isFSctl, compfilter));
02245 
02246         fsp=file_fsp((char *)*ppsetup, 4);
02247         /* this check is done in each implemented function case for now
02248            because I don't want to break anything... --metze
02249         FSP_BELONGS_CONN(fsp,conn);*/
02250 
02251         switch (function) {
02252         case FSCTL_SET_SPARSE:
02253                 /* pretend this succeeded - tho strictly we should
02254                    mark the file sparse (if the local fs supports it)
02255                    so we can know if we need to pre-allocate or not */
02256 
02257                 DEBUG(10,("FSCTL_SET_SPARSE: called on FID[0x%04X](but not implemented)\n", fidnum));
02258                 send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL,
02259                                 0);
02260                 return -1;
02261         
02262         case FSCTL_0x000900C0:
02263                 /* pretend this succeeded - don't know what this really is
02264                    but works ok like this --metze
02265                  */
02266 
02267                 DEBUG(10,("FSCTL_0x000900C0: called on FID[0x%04X](but not implemented)\n",fidnum));
02268                 send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL,
02269                                 0);
02270                 return -1;
02271 
02272         case FSCTL_GET_REPARSE_POINT:
02273                 /* pretend this fail - my winXP does it like this
02274                  * --metze
02275                  */
02276 
02277                 DEBUG(10,("FSCTL_GET_REPARSE_POINT: called on FID[0x%04X](but not implemented)\n",fidnum));
02278                 send_nt_replies(outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT,
02279                                 NULL, 0, NULL, 0);
02280                 return -1;
02281 
02282         case FSCTL_SET_REPARSE_POINT:
02283                 /* pretend this fail - I'm assuming this because of the FSCTL_GET_REPARSE_POINT case.
02284                  * --metze
02285                  */
02286 
02287                 DEBUG(10,("FSCTL_SET_REPARSE_POINT: called on FID[0x%04X](but not implemented)\n",fidnum));
02288                 send_nt_replies(outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT,
02289                                 NULL, 0, NULL, 0);
02290                 return -1;
02291                         
02292         case FSCTL_GET_SHADOW_COPY_DATA: /* don't know if this name is right...*/
02293         {
02294                 /*
02295                  * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots)
02296                  * and return their volume names.  If max_data_count is 16, then it is just
02297                  * asking for the number of volumes and length of the combined names.
02298                  *
02299                  * pdata is the data allocated by our caller, but that uses
02300                  * total_data_count (which is 0 in our case) rather than max_data_count.
02301                  * Allocate the correct amount and return the pointer to let
02302                  * it be deallocated when we return.
02303                  */
02304                 SHADOW_COPY_DATA *shadow_data = NULL;
02305                 TALLOC_CTX *shadow_mem_ctx = NULL;
02306                 BOOL labels = False;
02307                 uint32 labels_data_count = 0;
02308                 uint32 i;
02309                 char *cur_pdata;
02310 
02311                 FSP_BELONGS_CONN(fsp,conn);
02312 
02313                 if (max_data_count < 16) {
02314                         DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n",
02315                                 max_data_count));
02316                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
02317                 }
02318 
02319                 if (max_data_count > 16) {
02320                         labels = True;
02321                 }
02322 
02323                 shadow_mem_ctx = talloc_init("SHADOW_COPY_DATA");
02324                 if (shadow_mem_ctx == NULL) {
02325                         DEBUG(0,("talloc_init(SHADOW_COPY_DATA) failed!\n"));
02326                         return ERROR_NT(NT_STATUS_NO_MEMORY);
02327                 }
02328 
02329                 shadow_data = TALLOC_ZERO_P(shadow_mem_ctx,SHADOW_COPY_DATA);
02330                 if (shadow_data == NULL) {
02331                         DEBUG(0,("TALLOC_ZERO() failed!\n"));
02332                         talloc_destroy(shadow_mem_ctx);
02333                         return ERROR_NT(NT_STATUS_NO_MEMORY);
02334                 }
02335                 
02336                 shadow_data->mem_ctx = shadow_mem_ctx;
02337                 
02338                 /*
02339                  * Call the VFS routine to actually do the work.
02340                  */
02341                 if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) {
02342                         talloc_destroy(shadow_data->mem_ctx);
02343                         if (errno == ENOSYS) {
02344                                 DEBUG(5,("FSCTL_GET_SHADOW_COPY_DATA: connectpath %s, not supported.\n", 
02345                                         conn->connectpath));
02346                                 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
02347                         } else {
02348                                 DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: connectpath %s, failed.\n", 
02349                                         conn->connectpath));
02350                                 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);                        
02351                         }
02352                 }
02353 
02354                 labels_data_count = (shadow_data->num_volumes*2*sizeof(SHADOW_COPY_LABEL))+2;
02355 
02356                 if (!labels) {
02357                         data_count = 16;
02358                 } else {
02359                         data_count = 12+labels_data_count+4;
02360                 }
02361 
02362                 if (max_data_count<data_count) {
02363                         DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed!\n",
02364                                 max_data_count,data_count));
02365                         talloc_destroy(shadow_data->mem_ctx);
02366                         return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
02367                 }
02368 
02369                 pdata = nttrans_realloc(ppdata, data_count);
02370                 if (pdata == NULL) {
02371                         talloc_destroy(shadow_data->mem_ctx);
02372                         return ERROR_NT(NT_STATUS_NO_MEMORY);
02373                 }               
02374 
02375                 cur_pdata = pdata;
02376 
02377                 /* num_volumes 4 bytes */
02378                 SIVAL(pdata,0,shadow_data->num_volumes);
02379 
02380                 if (labels) {
02381                         /* num_labels 4 bytes */
02382                         SIVAL(pdata,4,shadow_data->num_volumes);
02383                 }
02384 
02385                 /* needed_data_count 4 bytes */
02386                 SIVAL(pdata,8,labels_data_count);
02387 
02388                 cur_pdata+=12;
02389 
02390                 DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n",
02391                         shadow_data->num_volumes,fsp->fsp_name));
02392                 if (labels && shadow_data->labels) {
02393                         for (i=0;i<shadow_data->num_volumes;i++) {
02394                                 srvstr_push(outbuf, cur_pdata, shadow_data->labels[i], 2*sizeof(SHADOW_COPY_LABEL), STR_UNICODE|STR_TERMINATE);
02395                                 cur_pdata+=2*sizeof(SHADOW_COPY_LABEL);
02396                                 DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i]));
02397                         }
02398                 }
02399 
02400                 talloc_destroy(shadow_data->mem_ctx);
02401 
02402                 send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0,
02403                                 pdata, data_count);
02404 
02405                 return -1;
02406         }
02407         
02408         case FSCTL_FIND_FILES_BY_SID: /* I hope this name is right */
02409         {
02410                 /* pretend this succeeded - 
02411                  * 
02412                  * we have to send back a list with all files owned by this SID
02413                  *
02414                  * but I have to check that --metze
02415                  */
02416                 DOM_SID sid;
02417                 uid_t uid;
02418                 size_t sid_len = MIN(data_count-4,SID_MAX_SIZE);
02419                 
02420                 DEBUG(10,("FSCTL_FIND_FILES_BY_SID: called on FID[0x%04X]\n",fidnum));
02421 
02422                 FSP_BELONGS_CONN(fsp,conn);
02423 
02424                 /* unknown 4 bytes: this is not the length of the sid :-(  */
02425                 /*unknown = IVAL(pdata,0);*/
02426                 
02427                 sid_parse(pdata+4,sid_len,&sid);
02428                 DEBUGADD(10,("for SID: %s\n",sid_string_static(&sid)));
02429 
02430                 if (!sid_to_uid(&sid, &uid)) {
02431                         DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
02432                                 sid_string_static(&sid),(unsigned long)sid_len));
02433                         uid = (-1);
02434                 }
02435                 
02436                 /* we can take a look at the find source :-)
02437                  *
02438                  * find ./ -uid $uid  -name '*'   is what we need here
02439                  *
02440                  *
02441                  * and send 4bytes len and then NULL terminated unicode strings
02442                  * for each file
02443                  *
02444                  * but I don't know how to deal with the paged results
02445                  * (maybe we can hang the result anywhere in the fsp struct)
02446                  *
02447                  * we don't send all files at once
02448                  * and at the next we should *not* start from the beginning, 
02449                  * so we have to cache the result 
02450                  *
02451                  * --metze
02452                  */
02453                 
02454                 /* this works for now... */
02455                 send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0,
02456                                 NULL, 0);
02457                 return -1;      
02458         }       
02459         default:
02460                 if (!logged_message) {
02461                         logged_message = True; /* Only print this once... */
02462                         DEBUG(0,("call_nt_transact_ioctl(0x%x): Currently not implemented.\n",
02463                                  function));
02464                 }
02465         }
02466 
02467         return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
02468 }
02469 
02470 
02471 #ifdef HAVE_SYS_QUOTAS
02472 /****************************************************************************
02473  Reply to get user quota 
02474 ****************************************************************************/
02475 
02476 static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, 
02477                                   uint16 **ppsetup, uint32 setup_count,
02478                                   char **ppparams, uint32 parameter_count,
02479                                   char **ppdata, uint32 data_count, uint32 max_data_count)
02480 {
02481         NTSTATUS nt_status = NT_STATUS_OK;
02482         char *params = *ppparams;
02483         char *pdata = *ppdata;
02484         char *entry;
02485         int data_len=0,param_len=0;
02486         int qt_len=0;
02487         int entry_len = 0;
02488         files_struct *fsp = NULL;
02489         uint16 level = 0;
02490         size_t sid_len;
02491         DOM_SID sid;
02492         BOOL start_enum = True;
02493         SMB_NTQUOTA_STRUCT qt;
02494         SMB_NTQUOTA_LIST *tmp_list;
02495         SMB_NTQUOTA_HANDLE *qt_handle = NULL;
02496 
02497         ZERO_STRUCT(qt);
02498 
02499         /* access check */
02500         if (current_user.ut.uid != 0) {
02501                 DEBUG(1,("get_user_quota: access_denied service [%s] user [%s]\n",
02502                         lp_servicename(SNUM(conn)),conn->user));
02503                 return ERROR_DOS(ERRDOS,ERRnoaccess);
02504         }
02505 
02506         /*
02507          * Ensure minimum number of parameters sent.
02508          */
02509 
02510         if (parameter_count < 4) {
02511                 DEBUG(0,("TRANSACT_GET_USER_QUOTA: requires %d >= 4 bytes parameters\n",parameter_count));
02512                 return ERROR_DOS(ERRDOS,ERRinvalidparam);
02513         }
02514         
02515         /* maybe we can check the quota_fnum */
02516         fsp = file_fsp(params,0);
02517         if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
02518                 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
02519                 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
02520         }
02521 
02522         /* the NULL pointer checking for fsp->fake_file_handle->pd
02523          * is done by CHECK_NTQUOTA_HANDLE_OK()
02524          */
02525         qt_handle = (SMB_NTQUOTA_HANDLE *)fsp->fake_file_handle->pd;
02526 
02527         level = SVAL(params,2);
02528         
02529         /* unknown 12 bytes leading in params */ 
02530         
02531         switch (level) {
02532                 case TRANSACT_GET_USER_QUOTA_LIST_CONTINUE:
02533                         /* seems that we should continue with the enum here --metze */
02534 
02535                         if (qt_handle->quota_list!=NULL && 
02536                             qt_handle->tmp_list==NULL) {
02537                 
02538                                 /* free the list */
02539                                 free_ntquota_list(&(qt_handle->quota_list));
02540 
02541                                 /* Realloc the size of parameters and data we will return */
02542                                 param_len = 4;
02543                                 params = nttrans_realloc(ppparams, param_len);
02544                                 if(params == NULL) {
02545                                         return ERROR_DOS(ERRDOS,ERRnomem);
02546                                 }
02547 
02548                                 data_len = 0;
02549                                 SIVAL(params,0,data_len);
02550 
02551                                 break;
02552                         }
02553 
02554                         start_enum = False;
02555 
02556                 case TRANSACT_GET_USER_QUOTA_LIST_START:
02557 
02558                         if (qt_handle->quota_list==NULL &&
02559                                 qt_handle->tmp_list==NULL) {
02560                                 start_enum = True;
02561                         }
02562 
02563                         if (start_enum && vfs_get_user_ntquota_list(fsp,&(qt_handle->quota_list))!=0)
02564                                 return ERROR_DOS(ERRSRV,ERRerror);
02565 
02566                         /* Realloc the size of parameters and data we will return */
02567                         param_len = 4;
02568                         params = nttrans_realloc(ppparams, param_len);
02569                         if(params == NULL) {
02570                                 return ERROR_DOS(ERRDOS,ERRnomem);
02571                         }
02572 
02573                         /* we should not trust the value in max_data_count*/
02574                         max_data_count = MIN(max_data_count,2048);
02575                         
02576                         pdata = nttrans_realloc(ppdata, max_data_count);/* should be max data count from client*/
02577                         if(pdata == NULL) {
02578                                 return ERROR_DOS(ERRDOS,ERRnomem);
02579                         }
02580 
02581                         entry = pdata;
02582 
02583                         /* set params Size of returned Quota Data 4 bytes*/
02584                         /* but set it later when we know it */
02585                 
02586                         /* for each entry push the data */
02587 
02588                         if (start_enum) {
02589                                 qt_handle->tmp_list = qt_handle->quota_list;
02590                         }
02591 
02592                         tmp_list = qt_handle->tmp_list;
02593 
02594                         for (;((tmp_list!=NULL)&&((qt_len +40+SID_MAX_SIZE)<max_data_count));
02595                                 tmp_list=tmp_list->next,entry+=entry_len,qt_len+=entry_len) {
02596 
02597                                 sid_len = sid_size(&tmp_list->quotas->sid);
02598                                 entry_len = 40 + sid_len;
02599 
02600                                 /* nextoffset entry 4 bytes */
02601                                 SIVAL(entry,0,entry_len);
02602                 
02603                                 /* then the len of the SID 4 bytes */
02604                                 SIVAL(entry,4,sid_len);
02605                                 
02606                                 /* unknown data 8 bytes SMB_BIG_UINT */
02607                                 SBIG_UINT(entry,8,(SMB_BIG_UINT)0); /* this is not 0 in windows...-metze*/
02608                                 
02609                                 /* the used disk space 8 bytes SMB_BIG_UINT */
02610                                 SBIG_UINT(entry,16,tmp_list->quotas->usedspace);
02611                                 
02612                                 /* the soft quotas 8 bytes SMB_BIG_UINT */
02613                                 SBIG_UINT(entry,24,tmp_list->quotas->softlim);
02614                                 
02615                                 /* the hard quotas 8 bytes SMB_BIG_UINT */
02616                                 SBIG_UINT(entry,32,tmp_list->quotas->hardlim);
02617                                 
02618                                 /* and now the SID */
02619                                 sid_linearize(entry+40, sid_len, &tmp_list->quotas->sid);
02620                         }
02621                         
02622                         qt_handle->tmp_list = tmp_list;
02623                         
02624                         /* overwrite the offset of the last entry */
02625                         SIVAL(entry-entry_len,0,0);
02626 
02627                         data_len = 4+qt_len;
02628                         /* overwrite the params quota_data_len */
02629                         SIVAL(params,0,data_len);
02630 
02631                         break;
02632 
02633                 case TRANSACT_GET_USER_QUOTA_FOR_SID:
02634                         
02635                         /* unknown 4 bytes IVAL(pdata,0) */     
02636                         
02637                         if (data_count < 8) {
02638                                 DEBUG(0,("TRANSACT_GET_USER_QUOTA_FOR_SID: requires %d >= %d bytes data\n",data_count,8));
02639                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);                               
02640                         }
02641 
02642                         sid_len = IVAL(pdata,4);
02643                         /* Ensure this is less than 1mb. */
02644                         if (sid_len > (1024*1024)) {
02645                                 return ERROR_DOS(ERRDOS,ERRnomem);
02646                         }
02647 
02648                         if (data_count < 8+sid_len) {
02649                                 DEBUG(0,("TRANSACT_GET_USER_QUOTA_FOR_SID: requires %d >= %lu bytes data\n",data_count,(unsigned long)(8+sid_len)));
02650                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);                               
02651                         }
02652 
02653                         data_len = 4+40+sid_len;
02654 
02655                         if (max_data_count < data_len) {
02656                                 DEBUG(0,("TRANSACT_GET_USER_QUOTA_FOR_SID: max_data_count(%d) < data_len(%d)\n",
02657                                         max_data_count, data_len));
02658                                 param_len = 4;
02659                                 SIVAL(params,0,data_len);
02660                                 data_len = 0;
02661                                 nt_status = NT_STATUS_BUFFER_TOO_SMALL;
02662                                 break;
02663                         }
02664 
02665                         sid_parse(pdata+8,sid_len,&sid);
02666                 
02667                         if (vfs_get_ntquota(fsp, SMB_USER_QUOTA_TYPE, &sid, &qt)!=0) {
02668                                 ZERO_STRUCT(qt);
02669                                 /* 
02670                                  * we have to return zero's in all fields 
02671                                  * instead of returning an error here
02672                                  * --metze
02673                                  */
02674                         }
02675 
02676                         /* Realloc the size of parameters and data we will return */
02677                         param_len = 4;
02678                         params = nttrans_realloc(ppparams, param_len);
02679                         if(params == NULL) {
02680                                 return ERROR_DOS(ERRDOS,ERRnomem);
02681                         }
02682 
02683                         pdata = nttrans_realloc(ppdata, data_len);
02684                         if(pdata == NULL) {
02685                                 return ERROR_DOS(ERRDOS,ERRnomem);
02686                         }
02687 
02688                         entry = pdata;
02689 
02690                         /* set params Size of returned Quota Data 4 bytes*/
02691                         SIVAL(params,0,data_len);
02692         
02693                         /* nextoffset entry 4 bytes */
02694                         SIVAL(entry,0,0);
02695         
02696                         /* then the len of the SID 4 bytes */
02697                         SIVAL(entry,4,sid_len);
02698                         
02699                         /* unknown data 8 bytes SMB_BIG_UINT */
02700                         SBIG_UINT(entry,8,(SMB_BIG_UINT)0); /* this is not 0 in windows...-mezte*/
02701                         
02702                         /* the used disk space 8 bytes SMB_BIG_UINT */
02703                         SBIG_UINT(entry,16,qt.usedspace);
02704                         
02705                         /* the soft quotas 8 bytes SMB_BIG_UINT */
02706                         SBIG_UINT(entry,24,qt.softlim);
02707                         
02708                         /* the hard quotas 8 bytes SMB_BIG_UINT */
02709                         SBIG_UINT(entry,32,qt.hardlim);
02710                         
02711                         /* and now the SID */
02712                         sid_linearize(entry+40, sid_len, &sid);
02713 
02714                         break;
02715 
02716                 default:
02717                         DEBUG(0,("do_nt_transact_get_user_quota: fnum %d unknown level 0x%04hX\n",fsp->fnum,level));
02718                         return ERROR_DOS(ERRSRV,ERRerror);
02719                         break;
02720         }
02721 
02722         send_nt_replies(outbuf, bufsize, nt_status, params, param_len,
02723                         pdata, data_len);
02724 
02725         return -1;
02726 }
02727 
02728 /****************************************************************************
02729  Reply to set user quota
02730 ****************************************************************************/
02731 
02732 static int call_nt_transact_set_user_quota(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, 
02733                                   uint16 **ppsetup, uint32 setup_count,
02734                                   char **ppparams, uint32 parameter_count,
02735                                   char **ppdata, uint32 data_count, uint32 max_data_count)
02736 {
02737         char *params = *ppparams;
02738         char *pdata = *ppdata;
02739         int data_len=0,param_len=0;
02740         SMB_NTQUOTA_STRUCT qt;
02741         size_t sid_len;
02742         DOM_SID sid;
02743         files_struct *fsp = NULL;
02744 
02745         ZERO_STRUCT(qt);
02746 
02747         /* access check */
02748         if (current_user.ut.uid != 0) {
02749                 DEBUG(1,("set_user_quota: access_denied service [%s] user [%s]\n",
02750                         lp_servicename(SNUM(conn)),conn->user));
02751                 return ERROR_DOS(ERRDOS,ERRnoaccess);
02752         }
02753 
02754         /*
02755          * Ensure minimum number of parameters sent.
02756          */
02757 
02758         if (parameter_count < 2) {
02759                 DEBUG(0,("TRANSACT_SET_USER_QUOTA: requires %d >= 2 bytes parameters\n",parameter_count));
02760                 return ERROR_DOS(ERRDOS,ERRinvalidparam);
02761         }
02762         
02763         /* maybe we can check the quota_fnum */
02764         fsp = file_fsp(params,0);
02765         if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
02766                 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
02767                 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
02768         }
02769 
02770         if (data_count < 40) {
02771                 DEBUG(0,("TRANSACT_SET_USER_QUOTA: requires %d >= %d bytes data\n",data_count,40));
02772                 return ERROR_DOS(ERRDOS,ERRunknownlevel);               
02773         }
02774 
02775         /* offset to next quota record.
02776          * 4 bytes IVAL(pdata,0)
02777          * unused here...
02778          */
02779 
02780         /* sid len */
02781         sid_len = IVAL(pdata,4);
02782 
02783         if (data_count < 40+sid_len) {
02784                 DEBUG(0,("TRANSACT_SET_USER_QUOTA: requires %d >= %lu bytes data\n",data_count,(unsigned long)40+sid_len));
02785                 return ERROR_DOS(ERRDOS,ERRunknownlevel);               
02786         }
02787 
02788         /* unknown 8 bytes in pdata 
02789          * maybe its the change time in NTTIME
02790          */
02791 
02792         /* the used space 8 bytes (SMB_BIG_UINT)*/
02793         qt.usedspace = (SMB_BIG_UINT)IVAL(pdata,16);
02794 #ifdef LARGE_SMB_OFF_T
02795         qt.usedspace |= (((SMB_BIG_UINT)IVAL(pdata,20)) << 32);
02796 #else /* LARGE_SMB_OFF_T */
02797         if ((IVAL(pdata,20) != 0)&&
02798                 ((qt.usedspace != 0xFFFFFFFF)||
02799                 (IVAL(pdata,20)!=0xFFFFFFFF))) {
02800                 /* more than 32 bits? */
02801                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
02802         }
02803 #endif /* LARGE_SMB_OFF_T */
02804 
02805         /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
02806         qt.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
02807 #ifdef LARGE_SMB_OFF_T
02808         qt.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
02809 #else /* LARGE_SMB_OFF_T */
02810         if ((IVAL(pdata,28) != 0)&&
02811                 ((qt.softlim != 0xFFFFFFFF)||
02812                 (IVAL(pdata,28)!=0xFFFFFFFF))) {
02813                 /* more than 32 bits? */
02814                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
02815         }
02816 #endif /* LARGE_SMB_OFF_T */
02817 
02818         /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
02819         qt.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
02820 #ifdef LARGE_SMB_OFF_T
02821         qt.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
02822 #else /* LARGE_SMB_OFF_T */
02823         if ((IVAL(pdata,36) != 0)&&
02824                 ((qt.hardlim != 0xFFFFFFFF)||
02825                 (IVAL(pdata,36)!=0xFFFFFFFF))) {
02826                 /* more than 32 bits? */
02827                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
02828         }
02829 #endif /* LARGE_SMB_OFF_T */
02830         
02831         sid_parse(pdata+40,sid_len,&sid);
02832         DEBUGADD(8,("SID: %s\n",sid_string_static(&sid)));
02833 
02834         /* 44 unknown bytes left... */
02835 
02836         if (vfs_set_ntquota(fsp, SMB_USER_QUOTA_TYPE, &sid, &qt)!=0) {
02837                 return ERROR_DOS(ERRSRV,ERRerror);      
02838         }
02839 
02840         send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, param_len,
02841                         pdata, data_len);
02842 
02843         return -1;
02844 }
02845 #endif /* HAVE_SYS_QUOTAS */
02846 
02847 static int handle_nttrans(connection_struct *conn,
02848                           struct trans_state *state,
02849                           char *inbuf, char *outbuf, int size, int bufsize)
02850 {
02851         int outsize;
02852 
02853         if (Protocol >= PROTOCOL_NT1) {
02854                 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
02855         }
02856 
02857         /* Now we must call the relevant NT_TRANS function */
02858         switch(state->call) {
02859                 case NT_TRANSACT_CREATE:
02860                 {
02861                         START_PROFILE(NT_transact_create);
02862                         outsize = call_nt_transact_create(conn, inbuf, outbuf,
02863                                                           size, bufsize, 
02864                                                         &state->setup, state->setup_count,
02865                                                         &state->param, state->total_param, 
02866                                                         &state->data, state->total_data,
02867                                                           state->max_data_return);
02868                         END_PROFILE(NT_transact_create);
02869                         break;
02870                 }
02871 
02872                 case NT_TRANSACT_IOCTL:
02873                 {
02874                         START_PROFILE(NT_transact_ioctl);
02875                         outsize = call_nt_transact_ioctl(conn, inbuf, outbuf,
02876                                                          size, bufsize, 
02877                                                          &state->setup, state->setup_count,
02878                                                          &state->param, state->total_param, 
02879                                                          &state->data, state->total_data, state->max_data_return);
02880                         END_PROFILE(NT_transact_ioctl);
02881                         break;
02882                 }
02883 
02884                 case NT_TRANSACT_SET_SECURITY_DESC:
02885                 {
02886                         START_PROFILE(NT_transact_set_security_desc);
02887                         outsize = call_nt_transact_set_security_desc(conn, inbuf, outbuf, 
02888                                                          size, bufsize, 
02889                                                          &state->setup, state->setup_count,
02890                                                          &state->param, state->total_param, 
02891                                                          &state->data, state->total_data, state->max_data_return);
02892                         END_PROFILE(NT_transact_set_security_desc);
02893                         break;
02894                 }
02895 
02896                 case NT_TRANSACT_NOTIFY_CHANGE:
02897                 {
02898                         START_PROFILE(NT_transact_notify_change);
02899                         outsize = call_nt_transact_notify_change(
02900                                 conn, inbuf, outbuf, size, bufsize, 
02901                                 &state->setup, state->setup_count,
02902                                 &state->param, state->total_param, 
02903                                 &state->data, state->total_data,
02904                                 state->max_data_return,
02905                                 state->max_param_return);
02906                         END_PROFILE(NT_transact_notify_change);
02907                         break;
02908                 }
02909 
02910                 case NT_TRANSACT_RENAME:
02911                 {
02912                         START_PROFILE(NT_transact_rename);
02913                         outsize = call_nt_transact_rename(conn, inbuf, outbuf,
02914                                                          size, bufsize, 
02915                                                          &state->setup, state->setup_count,
02916                                                          &state->param, state->total_param, 
02917                                                          &state->data, state->total_data, state->max_data_return);
02918                         END_PROFILE(NT_transact_rename);
02919                         break;
02920                 }
02921 
02922                 case NT_TRANSACT_QUERY_SECURITY_DESC:
02923                 {
02924                         START_PROFILE(NT_transact_query_security_desc);
02925                         outsize = call_nt_transact_query_security_desc(conn, inbuf, outbuf, 
02926                                                          size, bufsize, 
02927                                                          &state->setup, state->setup_count,
02928                                                          &state->param, state->total_param, 
02929                                                          &state->data, state->total_data, state->max_data_return);
02930                         END_PROFILE(NT_transact_query_security_desc);
02931                         break;
02932                 }
02933 
02934 #ifdef HAVE_SYS_QUOTAS
02935                 case NT_TRANSACT_GET_USER_QUOTA:
02936                 {
02937                         START_PROFILE(NT_transact_get_user_quota);
02938                         outsize = call_nt_transact_get_user_quota(conn, inbuf, outbuf, 
02939                                                          size, bufsize, 
02940                                                          &state->setup, state->setup_count,
02941                                                          &state->param, state->total_param, 
02942                                                          &state->data, state->total_data, state->max_data_return);
02943                         END_PROFILE(NT_transact_get_user_quota);
02944                         break;
02945                 }
02946 
02947                 case NT_TRANSACT_SET_USER_QUOTA:
02948                 {
02949                         START_PROFILE(NT_transact_set_user_quota);
02950                         outsize = call_nt_transact_set_user_quota(conn, inbuf, outbuf, 
02951                                                          size, bufsize, 
02952                                                          &state->setup, state->setup_count,
02953                                                          &state->param, state->total_param, 
02954                                                          &state->data, state->total_data, state->max_data_return);
02955                         END_PROFILE(NT_transact_set_user_quota);
02956                         break;                                  
02957                 }
02958 #endif /* HAVE_SYS_QUOTAS */
02959 
02960                 default:
02961                         /* Error in request */
02962                         DEBUG(0,("reply_nttrans: Unknown request %d in nttrans call\n",
02963                                  state->call));
02964                         return ERROR_DOS(ERRSRV,ERRerror);
02965         }
02966         return outsize;
02967 }
02968 
02969 /****************************************************************************
02970  Reply to a SMBNTtrans.
02971 ****************************************************************************/
02972 
02973 int reply_nttrans(connection_struct *conn,
02974                         char *inbuf,char *outbuf,int size,int bufsize)
02975 {
02976         int  outsize = 0;
02977         uint32 pscnt = IVAL(inbuf,smb_nt_ParameterCount);
02978         uint32 psoff = IVAL(inbuf,smb_nt_ParameterOffset);
02979         uint32 dscnt = IVAL(inbuf,smb_nt_DataCount);
02980         uint32 dsoff = IVAL(inbuf,smb_nt_DataOffset);
02981         uint32 av_size = size-4;
02982 
02983         uint16 function_code = SVAL( inbuf, smb_nt_Function);
02984         NTSTATUS result;
02985         struct trans_state *state;
02986 
02987         START_PROFILE(SMBnttrans);
02988 
02989         if (IS_IPC(conn) && (function_code != NT_TRANSACT_CREATE)) {
02990                 END_PROFILE(SMBnttrans);
02991                 return ERROR_DOS(ERRSRV,ERRaccess);
02992         }
02993 
02994         result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
02995         if (!NT_STATUS_IS_OK(result)) {
02996                 DEBUG(2, ("Got invalid nttrans request: %s\n", nt_errstr(result)));
02997                 END_PROFILE(SMBnttrans);
02998                 return ERROR_NT(result);
02999         }
03000 
03001         if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
03002                 END_PROFILE(SMBnttrans);
03003                 return ERROR_DOS(ERRSRV,ERRaccess);
03004         }
03005 
03006         state->cmd = SMBnttrans;
03007 
03008         state->mid = SVAL(inbuf,smb_mid);
03009         state->vuid = SVAL(inbuf,smb_uid);
03010         state->total_data = IVAL(inbuf, smb_nt_TotalDataCount);
03011         state->data = NULL;
03012         state->total_param = IVAL(inbuf, smb_nt_TotalParameterCount);
03013         state->param = NULL;
03014         state->max_data_return = IVAL(inbuf,smb_nt_MaxDataCount);       
03015         state->max_param_return = IVAL(inbuf,smb_nt_MaxParameterCount);
03016 
03017         /* setup count is in *words* */
03018         state->setup_count = 2*CVAL(inbuf,smb_nt_SetupCount); 
03019         state->setup = NULL;
03020         state->call = function_code;
03021 
03022         /* 
03023          * All nttrans messages we handle have smb_wct == 19 +
03024          * state->setup_count.  Ensure this is so as a sanity check.
03025          */
03026 
03027         if(CVAL(inbuf, smb_wct) != 19 + (state->setup_count/2)) {
03028                 DEBUG(2,("Invalid smb_wct %d in nttrans call (should be %d)\n",
03029                         CVAL(inbuf, smb_wct), 19 + (state->setup_count/2)));
03030                 goto bad_param;
03031         }
03032 
03033         /* Don't allow more than 128mb for each value. */
03034         if ((state->total_data > (1024*1024*128)) ||
03035             (state->total_param > (1024*1024*128))) {
03036                 END_PROFILE(SMBnttrans);
03037                 return ERROR_DOS(ERRDOS,ERRnomem);
03038         }
03039 
03040         if ((dscnt > state->total_data) || (pscnt > state->total_param))
03041                 goto bad_param;
03042 
03043         if (state->total_data)  {
03044                 /* Can't use talloc here, the core routines do realloc on the
03045                  * params and data. */
03046                 if ((state->data = (char *)SMB_MALLOC(state->total_data)) == NULL) {
03047                         DEBUG(0,("reply_nttrans: data malloc fail for %u "
03048                                  "bytes !\n", (unsigned int)state->total_data));
03049                         TALLOC_FREE(state);
03050                         END_PROFILE(SMBnttrans);
03051                         return(ERROR_DOS(ERRDOS,ERRnomem));
03052                 } 
03053 
03054                 if (dscnt > state->total_data ||
03055                                 dsoff+dscnt < dsoff) {
03056                         goto bad_param;
03057                 }
03058 
03059                 if (dsoff > av_size ||
03060                                 dscnt > av_size ||
03061                                 dsoff+dscnt > av_size) {
03062                         goto bad_param;
03063                 }
03064 
03065                 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
03066         }
03067 
03068         if (state->total_param) {
03069                 /* Can't use talloc here, the core routines do realloc on the
03070                  * params and data. */
03071                 if ((state->param = (char *)SMB_MALLOC(state->total_param)) == NULL) {
03072                         DEBUG(0,("reply_nttrans: param malloc fail for %u "
03073                                  "bytes !\n", (unsigned int)state->total_param));
03074                         SAFE_FREE(state->data);
03075                         TALLOC_FREE(state);
03076                         END_PROFILE(SMBnttrans);
03077                         return(ERROR_DOS(ERRDOS,ERRnomem));
03078                 } 
03079 
03080                 if (pscnt > state->total_param ||
03081                                 psoff+pscnt < psoff) {
03082                         goto bad_param;
03083                 }
03084 
03085                 if (psoff > av_size ||
03086                                 pscnt > av_size ||
03087                                 psoff+pscnt > av_size) {
03088                         goto bad_param;
03089                 }
03090 
03091                 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
03092         }
03093 
03094         state->received_data  = dscnt;
03095         state->received_param = pscnt;
03096 
03097         if(state->setup_count > 0) {
03098                 DEBUG(10,("reply_nttrans: state->setup_count = %d\n",
03099                           state->setup_count));
03100                 state->setup = (uint16 *)TALLOC(state, state->setup_count);
03101                 if (state->setup == NULL) {
03102                         DEBUG(0,("reply_nttrans : Out of memory\n"));
03103                         SAFE_FREE(state->data);
03104                         SAFE_FREE(state->param);
03105                         TALLOC_FREE(state);
03106                         END_PROFILE(SMBnttrans);
03107                         return ERROR_DOS(ERRDOS,ERRnomem);
03108                 }
03109 
03110                 if ((smb_nt_SetupStart + state->setup_count < smb_nt_SetupStart) ||
03111                     (smb_nt_SetupStart + state->setup_count < state->setup_count)) {
03112                         goto bad_param;
03113                 }
03114                 if (smb_nt_SetupStart + state->setup_count > size) {
03115                         goto bad_param;
03116                 }
03117 
03118                 memcpy( state->setup, &inbuf[smb_nt_SetupStart], state->setup_count);
03119                 dump_data(10, (char *)state->setup, state->setup_count);
03120         }
03121 
03122         if ((state->received_data == state->total_data) &&
03123             (state->received_param == state->total_param)) {
03124                 outsize = handle_nttrans(conn, state, inbuf, outbuf,
03125                                          size, bufsize);
03126                 SAFE_FREE(state->param);
03127                 SAFE_FREE(state->data);
03128                 TALLOC_FREE(state);
03129                 END_PROFILE(SMBnttrans);
03130                 return outsize;
03131         }
03132 
03133         DLIST_ADD(conn->pending_trans, state);
03134 
03135         /* We need to send an interim response then receive the rest
03136            of the parameter/data bytes */
03137         outsize = set_message(outbuf,0,0,False);
03138         show_msg(outbuf);
03139         END_PROFILE(SMBnttrans);
03140         return outsize;
03141 
03142   bad_param:
03143 
03144         DEBUG(0,("reply_nttrans: invalid trans parameters\n"));
03145         SAFE_FREE(state->data);
03146         SAFE_FREE(state->param);
03147         TALLOC_FREE(state);
03148         END_PROFILE(SMBnttrans);
03149         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
03150 }
03151         
03152 /****************************************************************************
03153  Reply to a SMBnttranss
03154  ****************************************************************************/
03155 
03156 int reply_nttranss(connection_struct *conn,  char *inbuf,char *outbuf,
03157                    int size,int bufsize)
03158 {
03159         int outsize = 0;
03160         uint32_t pcnt,poff,dcnt,doff,pdisp,ddisp;
03161         uint32_t av_size = size-4;
03162         struct trans_state *state;
03163 
03164         START_PROFILE(SMBnttranss);
03165 
03166         show_msg(inbuf);
03167 
03168         for (state = conn->pending_trans; state != NULL;
03169              state = state->next) {
03170                 if (state->mid == SVAL(inbuf,smb_mid)) {
03171                         break;
03172                 }
03173         }
03174 
03175         if ((state == NULL) || (state->cmd != SMBnttrans)) {
03176                 END_PROFILE(SMBnttranss);
03177                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
03178         }
03179 
03180         /* Revise state->total_param and state->total_data in case they have
03181            changed downwards */
03182         if (IVAL(inbuf, smb_nts_TotalParameterCount) < state->total_param) {
03183                 state->total_param = IVAL(inbuf, smb_nts_TotalParameterCount);
03184         }
03185         if (IVAL(inbuf, smb_nts_TotalDataCount) < state->total_data) {
03186                 state->total_data = IVAL(inbuf, smb_nts_TotalDataCount);
03187         }
03188 
03189         pcnt = IVAL(inbuf,smb_nts_ParameterCount);
03190         poff = IVAL(inbuf, smb_nts_ParameterOffset);
03191         pdisp = IVAL(inbuf, smb_nts_ParameterDisplacement);
03192 
03193         dcnt = IVAL(inbuf, smb_nts_DataCount);
03194         ddisp = IVAL(inbuf, smb_nts_DataDisplacement);
03195         doff = IVAL(inbuf, smb_nts_DataOffset);
03196 
03197         state->received_param += pcnt;
03198         state->received_data += dcnt;
03199                 
03200         if ((state->received_data > state->total_data) ||
03201             (state->received_param > state->total_param))
03202                 goto bad_param;
03203 
03204         if (pcnt) {
03205                 if (pdisp > state->total_param ||
03206                                 pcnt > state->total_param ||
03207                                 pdisp+pcnt > state->total_param ||
03208                                 pdisp+pcnt < pdisp) {
03209                         goto bad_param;
03210                 }
03211 
03212                 if (poff > av_size ||
03213                                 pcnt > av_size ||
03214                                 poff+pcnt > av_size ||
03215                                 poff+pcnt < poff) {
03216                         goto bad_param;
03217                 }
03218 
03219                 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
03220                        pcnt);
03221         }
03222 
03223         if (dcnt) {
03224                 if (ddisp > state->total_data ||
03225                                 dcnt > state->total_data ||
03226                                 ddisp+dcnt > state->total_data ||
03227                                 ddisp+dcnt < ddisp) {
03228                         goto bad_param;
03229                 }
03230 
03231                 if (doff > av_size ||
03232                                 dcnt > av_size ||
03233                                 doff+dcnt > av_size ||
03234                                 doff+dcnt < doff) {
03235                         goto bad_param;
03236                 }
03237 
03238                 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
03239                        dcnt);      
03240         }
03241 
03242         if ((state->received_param < state->total_param) ||
03243             (state->received_data < state->total_data)) {
03244                 END_PROFILE(SMBnttranss);
03245                 return -1;
03246         }
03247 
03248         /* construct_reply_common has done us the favor to pre-fill the
03249          * command field with SMBnttranss which is wrong :-)
03250          */
03251         SCVAL(outbuf,smb_com,SMBnttrans);
03252 
03253         outsize = handle_nttrans(conn, state, inbuf, outbuf,
03254                                  size, bufsize);
03255 
03256         DLIST_REMOVE(conn->pending_trans, state);
03257         SAFE_FREE(state->data);
03258         SAFE_FREE(state->param);
03259         TALLOC_FREE(state);
03260 
03261         if (outsize == 0) {
03262                 END_PROFILE(SMBnttranss);
03263                 return(ERROR_DOS(ERRSRV,ERRnosupport));
03264         }
03265         
03266         END_PROFILE(SMBnttranss);
03267         return(outsize);
03268 
03269   bad_param:
03270 
03271         DEBUG(0,("reply_nttranss: invalid trans parameters\n"));
03272         DLIST_REMOVE(conn->pending_trans, state);
03273         SAFE_FREE(state->data);
03274         SAFE_FREE(state->param);
03275         TALLOC_FREE(state);
03276         END_PROFILE(SMBnttranss);
03277         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
03278 }

Sambaに対してSat Aug 29 21:23:24 2009に生成されました。  doxygen 1.4.7