📄 nttrans.c
字号:
if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0) { return ret; } /* Realloc the size of parameters and data we will return */ params = nttrans_realloc(ppparams, 69); if(params == NULL) { return ERROR_DOS(ERRDOS,ERRnomem); } p = params; SCVAL(p,0,NO_OPLOCK_RETURN); p += 2; SSVAL(p,0,pnum); p += 2; SIVAL(p,0,FILE_WAS_OPENED); p += 8; p += 32; SIVAL(p,0,FILE_ATTRIBUTE_NORMAL); /* File Attributes. */ p += 20; /* File type. */ SSVAL(p,0,FILE_TYPE_MESSAGE_MODE_PIPE); /* Device state. */ SSVAL(p,2, 0x5FF); /* ? */ 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, 69, *ppdata, 0); return -1;}/**************************************************************************** Internal fn to set security descriptors.****************************************************************************/static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 security_info_sent){ prs_struct pd; SEC_DESC *psd = NULL; TALLOC_CTX *mem_ctx; BOOL ret; if (sd_len == 0 || !lp_nt_acl_support(SNUM(fsp->conn))) { return NT_STATUS_OK; } /* * Init the parse struct we will unmarshall from. */ if ((mem_ctx = talloc_init("set_sd")) == NULL) { DEBUG(0,("set_sd: talloc_init failed.\n")); return NT_STATUS_NO_MEMORY; } prs_init(&pd, 0, mem_ctx, UNMARSHALL); /* * Setup the prs_struct to point at the memory we just * allocated. */ prs_give_memory( &pd, data, sd_len, False); /* * Finally, unmarshall from the data buffer. */ if(!sec_io_desc( "sd data", &psd, &pd, 1)) { DEBUG(0,("set_sd: Error in unmarshalling security descriptor.\n")); /* * Return access denied for want of a better error message.. */ talloc_destroy(mem_ctx); return NT_STATUS_NO_MEMORY; } if (psd->off_owner_sid==0) { security_info_sent &= ~OWNER_SECURITY_INFORMATION; } if (psd->off_grp_sid==0) { security_info_sent &= ~GROUP_SECURITY_INFORMATION; } if (psd->off_sacl==0) { security_info_sent &= ~SACL_SECURITY_INFORMATION; } if (psd->off_dacl==0) { security_info_sent &= ~DACL_SECURITY_INFORMATION; } ret = SMB_VFS_FSET_NT_ACL( fsp, fsp->fh->fd, security_info_sent, psd); if (!ret) { talloc_destroy(mem_ctx); return NT_STATUS_ACCESS_DENIED; } talloc_destroy(mem_ctx); return NT_STATUS_OK;}/**************************************************************************** Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.****************************************************************************/ static struct ea_list *read_nttrans_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size){ struct ea_list *ea_list_head = NULL; size_t offset = 0; if (data_size < 4) { return NULL; } while (offset + 4 <= data_size) { size_t next_offset = IVAL(pdata,offset); struct ea_list *tmp; struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset + 4, data_size - offset - 4, NULL); DLIST_ADD_END(ea_list_head, eal, tmp); if (next_offset == 0) { break; } offset += next_offset; } return ea_list_head;}/**************************************************************************** Reply to a NT_TRANSACT_CREATE call (needs to process SD's).****************************************************************************/static int call_nt_transact_create(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, uint32 max_data_count){ pstring fname; char *params = *ppparams; char *data = *ppdata; /* 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; BOOL extended_oplock_granted = False; uint32 flags; uint32 access_mask; uint32 file_attributes; uint32 share_access; uint32 create_disposition; uint32 create_options; uint32 sd_len; uint32 ea_len; uint16 root_dir_fid; time_t c_time; struct ea_list *ea_list = NULL; TALLOC_CTX *ctx = NULL; char *pdata = NULL; NTSTATUS status; DEBUG(5,("call_nt_transact_create\n")); /* * If it's an IPC, use the pipe handler. */ if (IS_IPC(conn)) { if (lp_nt_pipe_support()) { return do_nt_transact_create_pipe(conn, inbuf, outbuf, length, bufsize, ppsetup, setup_count, ppparams, parameter_count, ppdata, data_count); } else { return ERROR_DOS(ERRDOS,ERRnoaccess); } } /* * Ensure minimum number of parameters sent. */ if(parameter_count < 54) { DEBUG(0,("call_nt_transact_create - insufficient parameters (%u)\n", (unsigned int)parameter_count)); return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } flags = IVAL(params,0); access_mask = IVAL(params,8); file_attributes = IVAL(params,20); share_access = IVAL(params,24); create_disposition = IVAL(params,28); create_options = IVAL(params,32); sd_len = IVAL(params,36); ea_len = IVAL(params,40); root_dir_fid = (uint16)IVAL(params,4); /* Ensure the data_len is correct for the sd and ea values given. */ if ((ea_len + sd_len > data_count) || (ea_len > data_count) || (sd_len > data_count) || (ea_len + sd_len < ea_len) || (ea_len + sd_len < sd_len)) { DEBUG(10,("call_nt_transact_create - ea_len = %u, sd_len = %u, data_count = %u\n", (unsigned int)ea_len, (unsigned int)sd_len, (unsigned int)data_count )); return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } if (ea_len) { if (!lp_ea_support(SNUM(conn))) { DEBUG(10,("call_nt_transact_create - ea_len = %u but EA's not supported.\n", (unsigned int)ea_len )); return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED); } if (ea_len < 10) { DEBUG(10,("call_nt_transact_create - ea_len = %u - too small (should be more than 10)\n", (unsigned int)ea_len )); return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } } if (create_options & FILE_OPEN_BY_FILE_ID) { return ERROR_NT(NT_STATUS_NOT_SUPPORTED); } /* * Get the file name. */ if(root_dir_fid != 0) { /* * 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); } if(!dir_fsp->is_directory) { 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); } /* * Check to see if this is a mac fork of some kind. */ if( is_ntfs_stream_name(fname)) { return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); } 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++; } { pstring tmpname; srvstr_get_path(inbuf, tmpname, params+53, sizeof(tmpname), parameter_count-53, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); } pstrcat(fname, tmpname); } } else { 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); } /* * Check to see if this is a mac fork of some kind. */ if( is_ntfs_stream_name(fname)) { return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); } } oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; /* * Check if POSIX semantics are wanted. */ set_posix_case_semantics(conn, file_attributes); RESOLVE_DFSPATH(fname, conn, inbuf, outbuf); unix_convert(fname,conn,0,&bad_path,&sbuf); if (bad_path) { restore_case_semantics(conn, file_attributes); 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); 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); return ERROR_NT(status); } } if (ea_len) { ctx = talloc_init("NTTRANS_CREATE_EA"); if (!ctx) { talloc_destroy(ctx); restore_case_semantics(conn, file_attributes); return ERROR_NT(NT_STATUS_NO_MEMORY); } pdata = data + sd_len; /* We have already checked that ea_len <= data_count here. */ ea_list = read_nttrans_ea_list(ctx, pdata, ea_len); if (!ea_list ) { talloc_destroy(ctx); restore_case_semantics(conn, file_attributes); return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } } /* * If it's a request for a directory open, deal with it separately. */ if(create_options & FILE_DIRECTORY_FILE) { /* Can't open a temp directory. IFS kit test. */ if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) { talloc_destroy(ctx); restore_case_semantics(conn, file_attributes); return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } oplock_request = 0; /* * We will get a create directory here if the Win32 * app specified a security descriptor in the * CreateDirectory() call. */ fsp = open_directory(conn, fname, &sbuf, access_mask, share_access, create_disposition, create_options, &info); if(!fsp) { talloc_destroy(ctx); restore_case_semantics(conn, file_attributes); return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } } else { /* * Ordinary file case. */ fsp = open_file_ntcreate(conn,fname,&sbuf, access_mask, share_access, create_disposition, create_options, file_attributes, oplock_request, &info); if (!fsp) { 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); 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) { talloc_destroy(ctx); restore_case_semantics(conn, file_attributes); return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } } else { talloc_destroy(ctx); restore_case_semantics(conn, file_attributes); 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); } } } /* * 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 * Patch for bug #2242 from Tom Lackemann <cessnatomny@yahoo.com>. */ if (lp_nt_acl_support(SNUM(conn)) && sd_len && info == FILE_WAS_CREATED) { uint32 saved_access_mask = fsp->access_mask; /* We have already checked that sd_len <= data_count here. */ fsp->access_mask = FILE_GENERIC_ALL; status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION); if (!NT_STATUS_IS_OK(status)) { talloc_destroy(ctx); close_file(fsp,False);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -