📄 nttrans.c
字号:
uint32 flags = IVAL(inbuf,smb_ntcreate_Flags); uint32 access_mask = IVAL(inbuf,smb_ntcreate_DesiredAccess); uint32 file_attributes = IVAL(inbuf,smb_ntcreate_FileAttributes); uint32 share_access = IVAL(inbuf,smb_ntcreate_ShareAccess); uint32 create_disposition = IVAL(inbuf,smb_ntcreate_CreateDisposition); uint32 create_options = IVAL(inbuf,smb_ntcreate_CreateOptions); uint16 root_dir_fid = (uint16)IVAL(inbuf,smb_ntcreate_RootDirectoryFid); /* Breakout the oplock request bits so we can set the reply bits separately. */ int oplock_request = 0; uint32 fattr=0; SMB_OFF_T file_len = 0; SMB_STRUCT_STAT sbuf; int info = 0; BOOL bad_path = False; files_struct *fsp=NULL; char *p = NULL; time_t c_time; BOOL extended_oplock_granted = False; NTSTATUS status; START_PROFILE(SMBntcreateX); DEBUG(10,("reply_ntcreateX: flags = 0x%x, access_mask = 0x%x \file_attributes = 0x%x, share_access = 0x%x, create_disposition = 0x%x \create_options = 0x%x root_dir_fid = 0x%x\n", (unsigned int)flags, (unsigned int)access_mask, (unsigned int)file_attributes, (unsigned int)share_access, (unsigned int)create_disposition, (unsigned int)create_options, (unsigned int)root_dir_fid )); /* If it's an IPC, use the pipe handler. */ if (IS_IPC(conn)) { if (lp_nt_pipe_support()) { END_PROFILE(SMBntcreateX); return do_ntcreate_pipe_open(conn,inbuf,outbuf,length,bufsize); } else { END_PROFILE(SMBntcreateX); return(ERROR_DOS(ERRDOS,ERRnoaccess)); } } if (create_options & FILE_OPEN_BY_FILE_ID) { END_PROFILE(SMBntcreateX); return ERROR_NT(NT_STATUS_NOT_SUPPORTED); } /* * Get the file name. */ if(root_dir_fid != 0) { /* * This filename is relative to a directory fid. */ pstring rel_fname; files_struct *dir_fsp = file_fsp(inbuf,smb_ntcreate_RootDirectoryFid); size_t dir_name_len; if(!dir_fsp) { END_PROFILE(SMBntcreateX); return(ERROR_DOS(ERRDOS,ERRbadfid)); } if(!dir_fsp->is_directory) { srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntcreateX); return ERROR_NT(status); } /* * Check to see if this is a mac fork of some kind. */ if( is_ntfs_stream_name(fname)) { END_PROFILE(SMBntcreateX); return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); } /* we need to handle the case when we get a relative open relative to a file and the pathname is blank - this is a reopen! (hint from demyn plantenberg) */ END_PROFILE(SMBntcreateX); return(ERROR_DOS(ERRDOS,ERRbadfid)); } /* * Copy in the base directory name. */ pstrcpy( fname, dir_fsp->fsp_name ); 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++; } srvstr_get_path(inbuf, rel_fname, smb_buf(inbuf), sizeof(rel_fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntcreateX); return ERROR_NT(status); } pstrcat(fname, rel_fname); } else { srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBntcreateX); return ERROR_NT(status); } /* * Check to see if this is a mac fork of some kind. */ if( is_ntfs_stream_name(fname)) { enum FAKE_FILE_TYPE fake_file_type = is_fake_file(fname); if (fake_file_type!=FAKE_FILE_TYPE_NONE) { /* * Here we go! support for changing the disk quotas --metze * * We need to fake up to open this MAGIC QUOTA file * and return a valid FID. * * w2k close this file directly after openening * xp also tries a QUERY_FILE_INFO on the file and then close it */ result = reply_ntcreate_and_X_quota(conn, inbuf, outbuf, length, bufsize, fake_file_type, fname); END_PROFILE(SMBntcreateX); return result; } else { END_PROFILE(SMBntcreateX); return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); } } } /* * Now contruct the smb_open_mode value from the filename, * desired access and the share access. */ RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; if (oplock_request) { oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; } /* * Ordinary file or directory. */ /* * Check if POSIX semantics are wanted. */ set_posix_case_semantics(conn, file_attributes); unix_convert(fname,conn,0,&bad_path,&sbuf); if (bad_path) { restore_case_semantics(conn, file_attributes); END_PROFILE(SMBntcreateX); return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); } /* All file access must go through check_name() */ if (!check_name(fname,conn)) { restore_case_semantics(conn, file_attributes); END_PROFILE(SMBntcreateX); return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); }#if 0 /* This is the correct thing to do (check every time) but can_delete is expensive (it may have to read the parent directory permissions). So for now we're not doing it unless we have a strong hint the client is really going to delete this file. */ if (desired_access & DELETE_ACCESS) {#else /* Setting FILE_SHARE_DELETE is the hint. */ if (lp_acl_check_permissions(SNUM(conn)) && (share_access & FILE_SHARE_DELETE) && (access_mask & DELETE_ACCESS)) {#endif status = can_delete(conn, fname, file_attributes, bad_path, True); /* We're only going to fail here if it's access denied, as that's the only error we care about for "can we delete this ?" questions. */ if (!NT_STATUS_IS_OK(status) && (NT_STATUS_EQUAL(status,NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(status,NT_STATUS_CANNOT_DELETE))) { restore_case_semantics(conn, file_attributes); END_PROFILE(SMBntcreateX); return ERROR_NT(NT_STATUS_ACCESS_DENIED); } } /* * If it's a request for a directory open, deal with it separately. */ if(create_options & FILE_DIRECTORY_FILE) { oplock_request = 0; /* Can't open a temp directory. IFS kit test. */ if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) { END_PROFILE(SMBntcreateX); return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } fsp = open_directory(conn, fname, &sbuf, access_mask, share_access, create_disposition, create_options, &info); restore_case_semantics(conn, file_attributes); if(!fsp) { END_PROFILE(SMBntcreateX); return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } } else { /* * Ordinary file case. */ /* NB. We have a potential bug here. If we * cause an oplock break to ourselves, then we * could end up processing filename related * SMB requests whilst we await the oplock * break response. As we may have changed the * filename case semantics to be POSIX-like, * this could mean a filename request could * fail when it should succeed. This is a rare * condition, but eventually we must arrange * to restore the correct case semantics * before issuing an oplock break request to * our client. JRA. */ fsp = open_file_ntcreate(conn,fname,&sbuf, access_mask, share_access, create_disposition, create_options, file_attributes, oplock_request, &info); if (!fsp) { /* We cheat here. There are two cases we * care about. One is a directory rename, * where the NT client will attempt to * open the source directory for * DELETE access. Note that when the * NT client does this it does *not* * set the directory bit in the * request packet. This is translated * into a read/write open * request. POSIX states that any open * for write request on a directory * will generate an EISDIR error, so * we can catch this here and open a * pseudo handle that is flagged as a * directory. The second is an open * for a permissions read only, which * we handle in the open_file_stat case. JRA. */ if(errno == EISDIR) { /* * Fail the open if it was explicitly a non-directory file. */ if (create_options & FILE_NON_DIRECTORY_FILE) { restore_case_semantics(conn, file_attributes); END_PROFILE(SMBntcreateX); return ERROR_FORCE_NT(NT_STATUS_FILE_IS_A_DIRECTORY); } oplock_request = 0; fsp = open_directory(conn, fname, &sbuf, access_mask, share_access, create_disposition, create_options, &info); if(!fsp) { restore_case_semantics(conn, file_attributes); END_PROFILE(SMBntcreateX); return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } } 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 set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } } } restore_case_semantics(conn, file_attributes); file_len = sbuf.st_size; fattr = dos_mode(conn,fname,&sbuf); if(fattr == 0) { fattr = FILE_ATTRIBUTE_NORMAL; } if (!fsp->is_directory && (fattr & aDIR)) { close_file(fsp,False); END_PROFILE(SMBntcreateX); return ERROR_DOS(ERRDOS,ERRnoaccess); } /* Save the requested allocation size. */ if ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN)) { SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize);#ifdef LARGE_SMB_OFF_T allocation_size |= (((SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize + 4)) << 32);#endif if (allocation_size && (allocation_size > (SMB_BIG_UINT)file_len)) { fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size); if (fsp->is_directory) { close_file(fsp,False); END_PROFILE(SMBntcreateX); /* Can't set allocation size on a directory. */ return ERROR_NT(NT_STATUS_ACCESS_DENIED); } if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) { close_file(fsp,False); END_PROFILE(SMBntcreateX); return ERROR_NT(NT_STATUS_DISK_FULL); } } else { fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)file_len); } } /* * If the caller set the extended oplock request bit * and we granted one (by whatever means) - set the * correct bit for extended oplock reply. */ if (oplock_request && lp_fake_oplocks(SNUM(conn))) { extended_oplock_granted = True; } if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { extended_oplock_granted = True; }#if 0 /* W2K sends back 42 words here ! If we do the same it breaks offline sync. Go figure... ? JRA. */ set_message(outbuf,42,0,True);#else set_message(outbuf,34,0,True);#endif p = outbuf + smb_vwv2; /* * Currently as we don't support level II oplocks we just report * exclusive & batch here. */ if (extended_oplock_granted) { if (flags & REQUEST_BATCH_OPLOCK) { SCVAL(p,0, BATCH_OPLOCK_RETURN); } else { SCVAL(p,0, EXCLUSIVE_OPLOCK_RETURN); } } else if (fsp->oplock_type == LEVEL_II_OPLOCK) { SCVAL(p,0, LEVEL_II_OPLOCK_RETURN); } else { SCVAL(p,0,NO_OPLOCK_RETURN); } p++; SSVAL(p,0,fsp->fnum); p += 2; if ((create_disposition == FILE_SUPERSEDE) && (info == FILE_WAS_OVERWRITTEN)) { SIVAL(p,0,FILE_WAS_SUPERSEDED); } else { SIVAL(p,0,info); } p += 4; /* Create time. */ c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))); if (lp_dos_filetime_resolution(SNUM(conn))) { c_time &= ~1; sbuf.st_atime &= ~1; sbuf.st_mtime &= ~1; sbuf.st_mtime &= ~1; } put_long_date(p,c_time); p += 8; put_long_date(p,sbuf.st_atime); /* access time */ p += 8; put_long_date(p,sbuf.st_mtime); /* write time */ p += 8; put_long_date(p,sbuf.st_mtime); /* change time */ p += 8; SIVAL(p,0,fattr); /* File Attributes. */ p += 4; SOFF_T(p, 0, get_allocation_size(conn,fsp,&sbuf)); p += 8; SOFF_T(p,0,file_len); p += 8; if (flags & EXTENDED_RESPONSE_REQUIRED) { SSVAL(p,2,0x7); } p += 4; SCVAL(p,0,fsp->is_directory ? 1 : 0); DEBUG(5,("reply_ntcreate_and_X: fnum = %d, open name = %s\n", fsp->fnum, fsp->fsp_name)); result = chain_reply(inbuf,outbuf,length,bufsize); END_PROFILE(SMBntcreateX); return result;}/**************************************************************************** Reply to a NT_TRANSACT_CREATE call to open a pipe.****************************************************************************/static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, char **ppsetup, uint32 setup_count, char **ppparams, uint32 parameter_count, char **ppdata, uint32 data_count){ pstring fname; char *params = *ppparams; int ret; int pnum = -1; char *p = NULL; NTSTATUS status; /* * Ensure minimum number of parameters sent. */ if(parameter_count < 54) { DEBUG(0,("do_nt_transact_create_pipe - insufficient parameters (%u)\n", (unsigned int)parameter_count)); return ERROR_DOS(ERRDOS,ERRnoaccess); } srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -