Ensure every use of push_ascii checks for error -1 condition.
[tprouty/samba.git] / source / smbd / nttrans.c
index e713922ecb265d38edd9943cd76e6d7b413ea4f9..45563b4a4f6b7976186ba7d33aadee00483a7ef2 100644 (file)
@@ -68,14 +68,8 @@ static char *nttrans_realloc(char **ptr, size_t size)
  HACK ! Always assumes smb_setup field is zero.
 ****************************************************************************/
 
-int send_nt_replies(const char *inbuf,
-                       char *outbuf,
-                       int bufsize,
-                       NTSTATUS nt_error,
-                       char *params,
-                       int paramsize,
-                       char *pdata,
-                       int datasize)
+int send_nt_replies(char *outbuf, int bufsize, NTSTATUS nt_error,
+                   char *params, int paramsize, char *pdata, int datasize)
 {
        int data_to_send = datasize;
        int params_to_send = paramsize;
@@ -91,7 +85,7 @@ int send_nt_replies(const char *inbuf,
         * transNT replies.
         */
 
-       set_message(inbuf,outbuf,18,0,True);
+       set_message(outbuf,18,0,True);
 
        if (NT_STATUS_V(nt_error)) {
                ERROR_NT(nt_error);
@@ -155,7 +149,7 @@ int send_nt_replies(const char *inbuf,
 
                total_sent_thistime = MIN(total_sent_thistime, useable_space);
 
-               set_message(inbuf,outbuf, 18, total_sent_thistime, True);
+               set_message(outbuf, 18, total_sent_thistime, True);
 
                /*
                 * Set total params and data to be sent.
@@ -359,7 +353,7 @@ static int nt_open_pipe(char *fname, connection_struct *conn,
                return(ERROR_DOS(ERRSRV,ERRnofids));
        }
 
-       /* TODO: Add pipe to db */
+       /* Add pipe to db */
        
        if ( !store_pipe_opendb( p ) ) {
                DEBUG(3,("nt_open_pipe: failed to store %s pipe open.\n", fname));
@@ -398,10 +392,10 @@ static int do_ntcreate_pipe_open(connection_struct *conn,
                 * the wcnt to 42 ? It's definately
                 * what happens on the wire....
                 */
-               set_message(inbuf,outbuf,50,0,True);
+               set_message(outbuf,50,0,True);
                SCVAL(outbuf,smb_wct,42);
        } else {
-               set_message(inbuf,outbuf,34,0,True);
+               set_message(outbuf,34,0,True);
        }
 
        p = outbuf + smb_vwv2;
@@ -460,7 +454,7 @@ int reply_ntcreate_and_X_quota(connection_struct *conn,
                return ERROR_NT(status);
        }
 
-       set_message(inbuf,outbuf,34,0,True);
+       set_message(outbuf,34,0,True);
        
        p = outbuf + smb_vwv2;
        
@@ -549,7 +543,6 @@ int reply_ntcreate_and_X(connection_struct *conn,
                 */
                pstring rel_fname;
                files_struct *dir_fsp = file_fsp(inbuf,smb_ntcreate_RootDirectoryFid);
-               size_t dir_name_len;
 
                if(!dir_fsp) {
                        END_PROFILE(SMBntcreateX);
@@ -589,15 +582,18 @@ int reply_ntcreate_and_X(connection_struct *conn,
                 */
 
                pstrcpy( fname, dir_fsp->fsp_name );
-               dir_name_len = strlen(fname);
 
-               /*
-                * Ensure it ends in a '\'.
-                */
+               if (ISDOT(fname)) {
+                       fname[0] = '\0';
+               } else {
+                       size_t dir_name_len = strlen(fname);
+                       /*
+                        * Ensure it ends in a '\'.
+                        */
 
-               if((fname[dir_name_len-1] != '\\') && (fname[dir_name_len-1] != '/')) {
-                       pstrcat(fname, "/");
-                       dir_name_len++;
+                       if((fname[dir_name_len-1] != '\\') && (fname[dir_name_len-1] != '/')) {
+                               pstrcat(fname, "/");
+                       }
                }
 
                srvstr_get_path(inbuf, rel_fname, smb_buf(inbuf), sizeof(rel_fname), 0, STR_TERMINATE, &status);
@@ -722,18 +718,6 @@ int reply_ntcreate_and_X(connection_struct *conn,
                                        create_options,
                                        new_file_attributes,
                                        &info, &fsp);
-
-               restore_case_semantics(conn, file_attributes);
-
-               if(!NT_STATUS_IS_OK(status)) {
-                       if (!use_nt_status() && NT_STATUS_EQUAL(
-                                   status, NT_STATUS_OBJECT_NAME_COLLISION)) {
-                               status = NT_STATUS_DOS(ERRDOS, ERRfilexists);
-                       }
-                       END_PROFILE(SMBntcreateX);
-                       return ERROR_NT(status);
-               }
-
        } else {
 
                /*
@@ -762,7 +746,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
                                        oplock_request,
                                        &info, &fsp);
 
-               if (!NT_STATUS_IS_OK(status)) { 
+               if (!NT_STATUS_IS_OK(status)) {
                        /* We cheat here. There are two cases we
                         * care about. One is a directory rename,
                         * where the NT client will attempt to
@@ -794,7 +778,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
                                        END_PROFILE(SMBntcreateX);
                                        return ERROR_FORCE_NT(NT_STATUS_FILE_IS_A_DIRECTORY);
                                }
-       
+
                                oplock_request = 0;
                                status = open_directory(conn, fname, &sbuf,
                                                        access_mask,
@@ -804,29 +788,23 @@ int reply_ntcreate_and_X(connection_struct *conn,
                                                        new_file_attributes,
                                                        &info, &fsp);
 
-                               if(!NT_STATUS_IS_OK(status)) {
-                                       restore_case_semantics(conn, file_attributes);
-                                       if (!use_nt_status() && NT_STATUS_EQUAL(
-                                                   status, NT_STATUS_OBJECT_NAME_COLLISION)) {
-                                               status = NT_STATUS_DOS(ERRDOS, ERRfilexists);
-                                       }
-                                       END_PROFILE(SMBntcreateX);
-                                       return ERROR_NT(status);
-                               }
-                       } else {
-                               restore_case_semantics(conn, file_attributes);
-                               END_PROFILE(SMBntcreateX);
-                               if (open_was_deferred(SVAL(inbuf,smb_mid))) {
-                                       /* We have re-scheduled this call. */
-                                       return -1;
-                               }
-                               return ERROR_NT(status);
                        }
-               } 
+               }
        }
-               
+
        restore_case_semantics(conn, file_attributes);
 
+       if(!NT_STATUS_IS_OK(status)) {
+               END_PROFILE(SMBntcreateX);
+
+               if (open_was_deferred(SVAL(inbuf,smb_mid))) {
+                       /* We have re-scheduled this call. */
+                       return -1;
+               }
+
+               return ERROR_OPEN(status);
+       }
+
        file_len = sbuf.st_size;
        fattr = dos_mode(conn,fname,&sbuf);
        if(fattr == 0) {
@@ -882,10 +860,10 @@ int reply_ntcreate_and_X(connection_struct *conn,
                 * the wcnt to 42 ? It's definately
                 * what happens on the wire....
                 */
-               set_message(inbuf,outbuf,50,0,True);
+               set_message(outbuf,50,0,True);
                SCVAL(outbuf,smb_wct,42);
        } else {
-               set_message(inbuf,outbuf,34,0,True);
+               set_message(outbuf,34,0,True);
        }
 
        p = outbuf + smb_vwv2;
@@ -1048,7 +1026,7 @@ static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, cha
        DEBUG(5,("do_nt_transact_create_pipe: open name = %s\n", fname));
        
        /* Send the required number of replies */
-       send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, param_len, *ppdata, 0);
+       send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, param_len, *ppdata, 0);
        
        return -1;
 }
@@ -1268,7 +1246,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
                 * This filename is relative to a directory fid.
                 */
                files_struct *dir_fsp = file_fsp(params,4);
-               size_t dir_name_len;
 
                if(!dir_fsp) {
                        return ERROR_DOS(ERRDOS,ERRbadfid);
@@ -1296,15 +1273,18 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
                 */
 
                pstrcpy( fname, dir_fsp->fsp_name );
-               dir_name_len = strlen(fname);
 
-               /*
-                * Ensure it ends in a '\'.
-                */
+                if (ISDOT(fname)) {
+                       fname[0] = '\0';
+               } else {
+                       size_t dir_name_len = strlen(fname);
+                       /*
+                        * Ensure it ends in a '\'.
+                        */
 
-               if((fname[dir_name_len-1] != '\\') && (fname[dir_name_len-1] != '/')) {
-                       pstrcat(fname, "/");
-                       dir_name_len++;
+                       if((fname[dir_name_len-1] != '\\') && (fname[dir_name_len-1] != '/')) {
+                               pstrcat(fname, "/");
+                       }
                }
 
                {
@@ -1422,11 +1402,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
                                        create_options,
                                        new_file_attributes,
                                        &info, &fsp);
-               if(!NT_STATUS_IS_OK(status)) {
-                       restore_case_semantics(conn, file_attributes);
-                       return ERROR_NT(status);
-               }
-
        } else {
 
                /*
@@ -1442,7 +1417,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
                                        oplock_request,
                                        &info, &fsp);
 
-               if (!NT_STATUS_IS_OK(status)) { 
+               if (!NT_STATUS_IS_OK(status)) {
                        if (NT_STATUS_EQUAL(status,
                                            NT_STATUS_FILE_IS_A_DIRECTORY)) {
 
@@ -1454,7 +1429,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
                                        restore_case_semantics(conn, file_attributes);
                                        return ERROR_FORCE_NT(NT_STATUS_FILE_IS_A_DIRECTORY);
                                }
-       
+
                                oplock_request = 0;
                                status = open_directory(conn, fname, &sbuf,
                                                        access_mask,
@@ -1463,26 +1438,26 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
                                                        create_options,
                                                        new_file_attributes,
                                                        &info, &fsp);
-                               if(!NT_STATUS_IS_OK(status)) {
-                                       restore_case_semantics(conn, file_attributes);
-                                       return ERROR_NT(status);
-                               }
-                       } else {
-                               restore_case_semantics(conn, file_attributes);
-                               if (open_was_deferred(SVAL(inbuf,smb_mid))) {
-                                       /* We have re-scheduled this call. */
-                                       return -1;
-                               }
-                               return ERROR_NT(status);
                        }
-               } 
+               }
+       }
+
+       restore_case_semantics(conn, file_attributes);
+       if(!NT_STATUS_IS_OK(status)) {
+
+               if (open_was_deferred(SVAL(inbuf,smb_mid))) {
+                       /* We have re-scheduled this call. */
+                       return -1;
+               }
+
+               return ERROR_OPEN(status);
        }
 
        /*
         * According to the MS documentation, the only time the security
         * descriptor is applied to the opened file is iff we *created* the
         * file; an existing file stays the same.
-        * 
+        *
         * Also, it seems (from observation) that you can open the file with
         * any access mask but you can still write the sd. We need to override
         * the granted access before we call set_sd
@@ -1643,7 +1618,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
        DEBUG(5,("call_nt_transact_create: open name = %s\n", fname));
 
        /* Send the required number of replies */
-       send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, param_len, *ppdata, 0);
+       send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, param_len, *ppdata, 0);
 
        return -1;
 }
@@ -1904,7 +1879,7 @@ int reply_ntrename(connection_struct *conn,
                return ERROR_NT(status);
        }
 
-       outsize = set_message(inbuf,outbuf,0,0,False);
+       outsize = set_message(outbuf,0,0,False);
   
        END_PROFILE(SMBntrename);
        return(outsize);
@@ -1985,7 +1960,7 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf,
                 * here.
                 */
 
-               change_notify_reply(inbuf, fsp->notify);
+               change_notify_reply(inbuf, max_param_count, fsp->notify);
 
                /*
                 * change_notify_reply() above has independently sent its
@@ -1998,7 +1973,8 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf,
         * No changes pending, queue the request
         */
 
-       status = change_notify_add_request(inbuf, filter, recursive, fsp);
+       status = change_notify_add_request(inbuf, max_param_count, filter,
+                       recursive, fsp);
        if (!NT_STATUS_IS_OK(status)) {
                return ERROR_NT(status);
        }
@@ -2049,7 +2025,7 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o
        /*
         * Rename was successful.
         */
-       send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0);
+       send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0);
        
        DEBUG(3,("nt transact rename from = %s, to = %s succeeded.\n", 
                 fsp->fsp_name, new_name));
@@ -2137,7 +2113,7 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, char *i
 
        if(max_data_count < sd_size) {
 
-               send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_BUFFER_TOO_SMALL,
+               send_nt_replies(outbuf, bufsize, NT_STATUS_BUFFER_TOO_SMALL,
                                params, 4, *ppdata, 0);
                talloc_destroy(mem_ctx);
                return -1;
@@ -2186,7 +2162,7 @@ security descriptor.\n"));
 
        talloc_destroy(mem_ctx);
 
-       send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, 4, data,
+       send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, 4, data,
                        (int)sd_size);
        return -1;
 }
@@ -2233,7 +2209,7 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, char *inb
 
   done:
 
-       send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0);
+       send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0);
        return -1;
 }
    
@@ -2279,31 +2255,19 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
                   so we can know if we need to pre-allocate or not */
 
                DEBUG(10,("FSCTL_SET_SPARSE: called on FID[0x%04X](but not implemented)\n", fidnum));
-               send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL,
+               send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL,
                                0);
                return -1;
        
-       case FSCTL_CREATE_OR_GET_OBJECT_ID:
-       {
-               unsigned char objid[16];
-
-               /* This should return the object-id on this file.
-                * I think I'll make this be the inode+dev. JRA.
+       case FSCTL_0x000900C0:
+               /* pretend this succeeded - don't know what this really is
+                  but works ok like this --metze
                 */
 
-               DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on FID[0x%04X]\n",fidnum));
-
-               data_count = 64;
-               pdata = nttrans_realloc(ppdata, data_count);
-               if (pdata == NULL) {
-                       return ERROR_NT(NT_STATUS_NO_MEMORY);
-               }
-               push_file_id_16(pdata, &fsp->file_id);
-               memcpy(pdata+16,create_volume_objectid(conn,objid),16);
-               push_file_id_16(pdata+32, &fsp->file_id);
-               send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, pdata, data_count);
+               DEBUG(10,("FSCTL_0x000900C0: called on FID[0x%04X](but not implemented)\n",fidnum));
+               send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL,
+                               0);
                return -1;
-       }
 
        case FSCTL_GET_REPARSE_POINT:
                /* pretend this fail - my winXP does it like this
@@ -2311,7 +2275,9 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
                 */
 
                DEBUG(10,("FSCTL_GET_REPARSE_POINT: called on FID[0x%04X](but not implemented)\n",fidnum));
-               return ERROR_NT(NT_STATUS_NOT_A_REPARSE_POINT);
+               send_nt_replies(outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT,
+                               NULL, 0, NULL, 0);
+               return -1;
 
        case FSCTL_SET_REPARSE_POINT:
                /* pretend this fail - I'm assuming this because of the FSCTL_GET_REPARSE_POINT case.
@@ -2319,7 +2285,9 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
                 */
 
                DEBUG(10,("FSCTL_SET_REPARSE_POINT: called on FID[0x%04X](but not implemented)\n",fidnum));
-               return ERROR_NT(NT_STATUS_NOT_A_REPARSE_POINT);
+               send_nt_replies(outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT,
+                               NULL, 0, NULL, 0);
+               return -1;
                        
        case FSCTL_GET_SHADOW_COPY_DATA: /* don't know if this name is right...*/
        {
@@ -2431,7 +2399,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
 
                talloc_destroy(shadow_data->mem_ctx);
 
-               send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0,
+               send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0,
                                pdata, data_count);
 
                return -1;
@@ -2484,7 +2452,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
                 */
                
                /* this works for now... */
-               send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0,
+               send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0,
                                NULL, 0);
                return -1;      
        }       
@@ -2751,7 +2719,7 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf,
                        break;
        }
 
-       send_nt_replies(inbuf, outbuf, bufsize, nt_status, params, param_len,
+       send_nt_replies(outbuf, bufsize, nt_status, params, param_len,
                        pdata, data_len);
 
        return -1;
@@ -2869,7 +2837,7 @@ static int call_nt_transact_set_user_quota(connection_struct *conn, char *inbuf,
                return ERROR_DOS(ERRSRV,ERRerror);      
        }
 
-       send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, param_len,
+       send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, param_len,
                        pdata, data_len);
 
        return -1;
@@ -3135,7 +3103,7 @@ int reply_nttrans(connection_struct *conn,
                }
 
                memcpy( state->setup, &inbuf[smb_nt_SetupStart], state->setup_count);
-               dump_data(10, (uint8 *)state->setup, state->setup_count);
+               dump_data(10, (char *)state->setup, state->setup_count);
        }
 
        if ((state->received_data == state->total_data) &&
@@ -3153,7 +3121,7 @@ int reply_nttrans(connection_struct *conn,
 
        /* We need to send an interim response then receive the rest
           of the parameter/data bytes */
-       outsize = set_message(inbuf,outbuf,0,0,False);
+       outsize = set_message(outbuf,0,0,False);
        show_msg(outbuf);
        END_PROFILE(SMBnttrans);
        return outsize;