From 6088e554f542c62405148c60fe5dedbee1c9cdd0 Mon Sep 17 00:00:00 2001 From: Tim Prouty Date: Thu, 4 Jun 2009 18:39:55 -0700 Subject: s3: Make all callers of SMB_VFS_CREATEFILE call unix_convert first This step is a requirement to change SMB_VFS_CREATEFILE to take an smb_filename struct. --- source3/rpc_server/srv_srvsvc_nt.c | 56 ++++++++++++--- source3/smbd/nttrans.c | 114 ++++++++++++++++------------- source3/smbd/reply.c | 142 +++++++++++++++++++++---------------- source3/smbd/smb2_create.c | 35 ++++++--- source3/smbd/trans2.c | 58 +++++++++------ 5 files changed, 256 insertions(+), 149 deletions(-) diff --git a/source3/rpc_server/srv_srvsvc_nt.c b/source3/rpc_server/srv_srvsvc_nt.c index 4f0e48bd9d..2df7232351 100644 --- a/source3/rpc_server/srv_srvsvc_nt.c +++ b/source3/rpc_server/srv_srvsvc_nt.c @@ -2032,6 +2032,8 @@ WERROR _srvsvc_NetRemoteTOD(pipes_struct *p, WERROR _srvsvc_NetGetFileSecurity(pipes_struct *p, struct srvsvc_NetGetFileSecurity *r) { + struct smb_filename *smb_fname = NULL; + char *fname = NULL; SEC_DESC *psd = NULL; size_t sd_size; fstring servicename; @@ -2065,12 +2067,25 @@ WERROR _srvsvc_NetGetFileSecurity(pipes_struct *p, goto error_exit; } + nt_status = unix_convert(talloc_tos(), conn, r->in.file, &smb_fname, + 0); + if (!NT_STATUS_IS_OK(nt_status)) { + werr = ntstatus_to_werror(nt_status); + goto error_exit; + } + + nt_status = get_full_smb_filename(talloc_tos(), smb_fname, &fname); + if (!NT_STATUS_IS_OK(nt_status)) { + werr = ntstatus_to_werror(nt_status); + goto error_exit; + } + nt_status = SMB_VFS_CREATE_FILE( conn, /* conn */ NULL, /* req */ 0, /* root_dir_fid */ - r->in.file, /* fname */ - CFF_DOS_PATH, /* create_file_flags */ + fname, /* fname */ + 0, /* create_file_flags */ FILE_READ_ATTRIBUTES, /* access_mask */ FILE_SHARE_READ|FILE_SHARE_WRITE, /* share_access */ FILE_OPEN, /* create_disposition*/ @@ -2086,7 +2101,7 @@ WERROR _srvsvc_NetGetFileSecurity(pipes_struct *p, if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(3,("_srvsvc_NetGetFileSecurity: can't open %s\n", - r->in.file)); + fname)); werr = ntstatus_to_werror(nt_status); goto error_exit; } @@ -2098,7 +2113,7 @@ WERROR _srvsvc_NetGetFileSecurity(pipes_struct *p, if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(3,("_srvsvc_NetGetFileSecurity: Unable to get NT ACL " - "for file %s\n", r->in.file)); + "for file %s\n", fname)); werr = ntstatus_to_werror(nt_status); goto error_exit; } @@ -2121,7 +2136,8 @@ WERROR _srvsvc_NetGetFileSecurity(pipes_struct *p, close_file(NULL, fsp, NORMAL_CLOSE); vfs_ChDir(conn, oldcwd); conn_free_internal(conn); - return WERR_OK; + werr = WERR_OK; + goto done; error_exit: @@ -2137,6 +2153,9 @@ error_exit: conn_free_internal(conn); } + done: + TALLOC_FREE(smb_fname); + return werr; } @@ -2148,6 +2167,8 @@ error_exit: WERROR _srvsvc_NetSetFileSecurity(pipes_struct *p, struct srvsvc_NetSetFileSecurity *r) { + struct smb_filename *smb_fname = NULL; + char *fname = NULL; fstring servicename; files_struct *fsp = NULL; SMB_STRUCT_STAT st; @@ -2180,12 +2201,25 @@ WERROR _srvsvc_NetSetFileSecurity(pipes_struct *p, goto error_exit; } + nt_status = unix_convert(talloc_tos(), conn, r->in.file, &smb_fname, + 0); + if (!NT_STATUS_IS_OK(nt_status)) { + werr = ntstatus_to_werror(nt_status); + goto error_exit; + } + + nt_status = get_full_smb_filename(talloc_tos(), smb_fname, &fname); + if (!NT_STATUS_IS_OK(nt_status)) { + werr = ntstatus_to_werror(nt_status); + goto error_exit; + } + nt_status = SMB_VFS_CREATE_FILE( conn, /* conn */ NULL, /* req */ 0, /* root_dir_fid */ - r->in.file, /* fname */ - CFF_DOS_PATH, /* create_file_flags */ + fname, /* fname */ + 0, /* create_file_flags */ FILE_WRITE_ATTRIBUTES, /* access_mask */ FILE_SHARE_READ|FILE_SHARE_WRITE, /* share_access */ FILE_OPEN, /* create_disposition*/ @@ -2201,7 +2235,7 @@ WERROR _srvsvc_NetSetFileSecurity(pipes_struct *p, if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(3,("_srvsvc_NetSetFileSecurity: can't open %s\n", - r->in.file)); + fname)); werr = ntstatus_to_werror(nt_status); goto error_exit; } @@ -2240,7 +2274,8 @@ WERROR _srvsvc_NetSetFileSecurity(pipes_struct *p, close_file(NULL, fsp, NORMAL_CLOSE); vfs_ChDir(conn, oldcwd); conn_free_internal(conn); - return WERR_OK; + werr = WERR_OK; + goto done; error_exit: @@ -2256,6 +2291,9 @@ error_exit: conn_free_internal(conn); } + done: + TALLOC_FREE(smb_fname); + return werr; } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 4c216cc6be..11d1c4b8a9 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -416,6 +416,7 @@ static void do_ntcreate_pipe_open(connection_struct *conn, void reply_ntcreate_and_X(struct smb_request *req) { connection_struct *conn = req->conn; + struct smb_filename *smb_fname = NULL; char *fname = NULL; uint32 flags; uint32 access_mask; @@ -429,7 +430,6 @@ void reply_ntcreate_and_X(struct smb_request *req) reply bits separately. */ uint32 fattr=0; SMB_OFF_T file_len = 0; - SMB_STRUCT_STAT sbuf; int info = 0; files_struct *fsp = NULL; char *p = NULL; @@ -443,8 +443,6 @@ void reply_ntcreate_and_X(struct smb_request *req) START_PROFILE(SMBntcreateX); - SET_STAT_INVALID(sbuf); - if (req->wct < 24) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); return; @@ -468,8 +466,7 @@ void reply_ntcreate_and_X(struct smb_request *req) if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); - END_PROFILE(SMBntcreateX); - return; + goto out; } DEBUG(10,("reply_ntcreate_and_X: flags = 0x%x, access_mask = 0x%x " @@ -498,12 +495,10 @@ void reply_ntcreate_and_X(struct smb_request *req) if (IS_IPC(conn)) { if (lp_nt_pipe_support()) { do_ntcreate_pipe_open(conn, req); - END_PROFILE(SMBntcreateX); - return; + goto out; } reply_doserror(req, ERRDOS, ERRnoaccess); - END_PROFILE(SMBntcreateX); - return; + goto out; } oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; @@ -512,12 +507,24 @@ void reply_ntcreate_and_X(struct smb_request *req) ? BATCH_OPLOCK : 0; } + status = unix_convert(ctx, conn, fname, &smb_fname, 0); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + goto out; + } + + status = get_full_smb_filename(ctx, smb_fname, &fname); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + goto out; + } + status = SMB_VFS_CREATE_FILE( conn, /* conn */ req, /* req */ root_dir_fid, /* root_dir_fid */ fname, /* fname */ - CFF_DOS_PATH, /* create_file_flags */ + 0, /* create_file_flags */ access_mask, /* access_mask */ share_access, /* share_access */ create_disposition, /* create_disposition*/ @@ -529,13 +536,12 @@ void reply_ntcreate_and_X(struct smb_request *req) NULL, /* ea_list */ &fsp, /* result */ &info, /* pinfo */ - &sbuf); /* psbuf */ + &smb_fname->st); /* psbuf */ if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(req->mid)) { /* We have re-scheduled this call, no error. */ - END_PROFILE(SMBntcreateX); - return; + goto out; } if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) { reply_botherror(req, status, ERRDOS, ERRfilexists); @@ -543,8 +549,7 @@ void reply_ntcreate_and_X(struct smb_request *req) else { reply_nterror(req, status); } - END_PROFILE(SMBntcreateX); - return; + goto out; } /* @@ -572,8 +577,8 @@ void reply_ntcreate_and_X(struct smb_request *req) oplock_granted = NO_OPLOCK_RETURN; } - file_len = sbuf.st_ex_size; - fattr = dos_mode(conn,fsp->fsp_name,&sbuf); + file_len = smb_fname->st.st_ex_size; + fattr = dos_mode(conn,fsp->fsp_name,&smb_fname->st); if (fattr == 0) { fattr = FILE_ATTRIBUTE_NORMAL; } @@ -606,9 +611,9 @@ void reply_ntcreate_and_X(struct smb_request *req) p += 4; /* Create time. */ - c_timespec = sbuf.st_ex_btime; - a_timespec = sbuf.st_ex_atime; - m_timespec = sbuf.st_ex_mtime; + c_timespec = smb_fname->st.st_ex_btime; + a_timespec = smb_fname->st.st_ex_atime; + m_timespec = smb_fname->st.st_ex_mtime; if (lp_dos_filetime_resolution(SNUM(conn))) { dos_filetime_timespec(&c_timespec); @@ -626,7 +631,7 @@ void reply_ntcreate_and_X(struct smb_request *req) p += 8; SIVAL(p,0,fattr); /* File Attributes. */ p += 4; - SOFF_T(p, 0, SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf)); + SOFF_T(p, 0, SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&smb_fname->st)); p += 8; SOFF_T(p,0,file_len); p += 8; @@ -639,8 +644,8 @@ void reply_ntcreate_and_X(struct smb_request *req) if (flags & EXTENDED_RESPONSE_REQUIRED) { uint32 perms = 0; p += 25; - if (fsp->is_directory - || can_write_to_file(conn, fsp->fsp_name, &sbuf)) { + if (fsp->is_directory || + can_write_to_file(conn, fsp->fsp_name, &smb_fname->st)) { perms = FILE_GENERIC_ALL; } else { perms = FILE_GENERIC_READ|FILE_EXECUTE; @@ -652,6 +657,8 @@ void reply_ntcreate_and_X(struct smb_request *req) fsp->fnum, fsp->fsp_name)); chain_reply(req); + out: + TALLOC_FREE(smb_fname); END_PROFILE(SMBntcreateX); return; } @@ -837,13 +844,13 @@ static void call_nt_transact_create(connection_struct *conn, char **ppdata, uint32 data_count, uint32 max_data_count) { + struct smb_filename *smb_fname = NULL; char *fname = NULL; char *params = *ppparams; char *data = *ppdata; /* Breakout the oplock request bits so we can set the reply bits separately. */ uint32 fattr=0; SMB_OFF_T file_len = 0; - SMB_STRUCT_STAT sbuf; int info = 0; files_struct *fsp = NULL; char *p = NULL; @@ -868,8 +875,6 @@ static void call_nt_transact_create(connection_struct *conn, uint8_t oplock_granted; TALLOC_CTX *ctx = talloc_tos(); - SET_STAT_INVALID(sbuf); - DEBUG(5,("call_nt_transact_create\n")); /* @@ -883,10 +888,10 @@ static void call_nt_transact_create(connection_struct *conn, ppsetup, setup_count, ppparams, parameter_count, ppdata, data_count); - return; + goto out; } reply_doserror(req, ERRDOS, ERRnoaccess); - return; + goto out; } /* @@ -896,7 +901,7 @@ static void call_nt_transact_create(connection_struct *conn, if(parameter_count < 54) { DEBUG(0,("call_nt_transact_create - insufficient parameters (%u)\n", (unsigned int)parameter_count)); reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - return; + goto out; } flags = IVAL(params,0); @@ -927,7 +932,7 @@ static void call_nt_transact_create(connection_struct *conn, "%u, data_count = %u\n", (unsigned int)ea_len, (unsigned int)sd_len, (unsigned int)data_count)); reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - return; + goto out; } if (sd_len) { @@ -941,7 +946,7 @@ static void call_nt_transact_create(connection_struct *conn, "unmarshall_sec_desc failed: %s\n", nt_errstr(status))); reply_nterror(req, status); - return; + goto out; } } @@ -951,7 +956,7 @@ static void call_nt_transact_create(connection_struct *conn, "EA's not supported.\n", (unsigned int)ea_len)); reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED); - return; + goto out; } if (ea_len < 10) { @@ -959,7 +964,7 @@ static void call_nt_transact_create(connection_struct *conn, "too small (should be more than 10)\n", (unsigned int)ea_len )); reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - return; + goto out; } /* We have already checked that ea_len <= data_count here. */ @@ -967,7 +972,7 @@ static void call_nt_transact_create(connection_struct *conn, ea_len); if (ea_list == NULL) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - return; + goto out; } } @@ -976,7 +981,7 @@ static void call_nt_transact_create(connection_struct *conn, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); - return; + goto out; } oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; @@ -985,12 +990,24 @@ static void call_nt_transact_create(connection_struct *conn, ? BATCH_OPLOCK : 0; } + status = unix_convert(ctx, conn, fname, &smb_fname, 0); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + goto out; + } + + status = get_full_smb_filename(ctx, smb_fname, &fname); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + goto out; + } + status = SMB_VFS_CREATE_FILE( conn, /* conn */ req, /* req */ root_dir_fid, /* root_dir_fid */ fname, /* fname */ - CFF_DOS_PATH, /* create_file_flags */ + 0, /* create_file_flags */ access_mask, /* access_mask */ share_access, /* share_access */ create_disposition, /* create_disposition*/ @@ -1002,7 +1019,7 @@ static void call_nt_transact_create(connection_struct *conn, ea_list, /* ea_list */ &fsp, /* result */ &info, /* pinfo */ - &sbuf); /* psbuf */ + &smb_fname->st); /* psbuf */ if(!NT_STATUS_IS_OK(status)) { if (open_was_deferred(req->mid)) { @@ -1010,7 +1027,7 @@ static void call_nt_transact_create(connection_struct *conn, return; } reply_openerror(req, status); - return; + goto out; } /* @@ -1038,8 +1055,8 @@ static void call_nt_transact_create(connection_struct *conn, oplock_granted = NO_OPLOCK_RETURN; } - file_len = sbuf.st_ex_size; - fattr = dos_mode(conn,fsp->fsp_name,&sbuf); + file_len = smb_fname->st.st_ex_size; + fattr = dos_mode(conn, fsp->fsp_name, &smb_fname->st); if (fattr == 0) { fattr = FILE_ATTRIBUTE_NORMAL; } @@ -1054,7 +1071,7 @@ static void call_nt_transact_create(connection_struct *conn, params = nttrans_realloc(ppparams, param_len); if(params == NULL) { reply_doserror(req, ERRDOS, ERRnomem); - return; + goto out; } p = params; @@ -1072,9 +1089,9 @@ static void call_nt_transact_create(connection_struct *conn, p += 8; /* Create time. */ - c_timespec = sbuf.st_ex_btime; - a_timespec = sbuf.st_ex_atime; - m_timespec = sbuf.st_ex_mtime; + c_timespec = smb_fname->st.st_ex_btime; + a_timespec = smb_fname->st.st_ex_atime; + m_timespec = smb_fname->st.st_ex_mtime; if (lp_dos_filetime_resolution(SNUM(conn))) { dos_filetime_timespec(&c_timespec); @@ -1092,7 +1109,7 @@ static void call_nt_transact_create(connection_struct *conn, p += 8; SIVAL(p,0,fattr); /* File Attributes. */ p += 4; - SOFF_T(p, 0, SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf)); + SOFF_T(p, 0, SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st)); p += 8; SOFF_T(p,0,file_len); p += 8; @@ -1105,8 +1122,8 @@ static void call_nt_transact_create(connection_struct *conn, if (flags & EXTENDED_RESPONSE_REQUIRED) { uint32 perms = 0; p += 25; - if (fsp->is_directory - || can_write_to_file(conn, fsp->fsp_name, &sbuf)) { + if (fsp->is_directory || + can_write_to_file(conn, fsp->fsp_name, &smb_fname->st)) { perms = FILE_GENERIC_ALL; } else { perms = FILE_GENERIC_READ|FILE_EXECUTE; @@ -1118,7 +1135,8 @@ static void call_nt_transact_create(connection_struct *conn, /* Send the required number of replies */ send_nt_replies(conn, req, NT_STATUS_OK, params, param_len, *ppdata, 0); - + out: + TALLOC_FREE(smb_fname); return; } diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 70d5537e04..844bcc1882 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1702,12 +1702,12 @@ void reply_fclose(struct smb_request *req) void reply_open(struct smb_request *req) { connection_struct *conn = req->conn; + struct smb_filename *smb_fname = NULL; char *fname = NULL; uint32 fattr=0; SMB_OFF_T size = 0; time_t mtime=0; int info; - SMB_STRUCT_STAT sbuf; files_struct *fsp; int oplock_request; int deny_mode; @@ -1721,12 +1721,9 @@ void reply_open(struct smb_request *req) START_PROFILE(SMBopen); - SET_STAT_INVALID(sbuf); - if (req->wct < 2) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - END_PROFILE(SMBopen); - return; + goto out; } oplock_request = CORE_OPLOCK_REQUEST(req->inbuf); @@ -1737,8 +1734,7 @@ void reply_open(struct smb_request *req) STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); - END_PROFILE(SMBopen); - return; + goto out; } if (!map_open_params_to_ntcreate( @@ -1749,12 +1745,24 @@ void reply_open(struct smb_request *req) return; } + status = unix_convert(ctx, conn, fname, &smb_fname, 0); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + goto out; + } + + status = get_full_smb_filename(ctx, smb_fname, &fname); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + goto out; + } + status = SMB_VFS_CREATE_FILE( conn, /* conn */ req, /* req */ 0, /* root_dir_fid */ fname, /* fname */ - CFF_DOS_PATH, /* create_file_flags */ + 0, /* create_file_flags */ access_mask, /* access_mask */ share_mode, /* share_access */ create_disposition, /* create_disposition*/ @@ -1766,29 +1774,26 @@ void reply_open(struct smb_request *req) NULL, /* ea_list */ &fsp, /* result */ &info, /* pinfo */ - &sbuf); /* psbuf */ + &smb_fname->st); /* psbuf */ if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(req->mid)) { /* We have re-scheduled this call. */ - END_PROFILE(SMBopen); - return; + goto out; } reply_openerror(req, status); - END_PROFILE(SMBopen); - return; + goto out; } - size = sbuf.st_ex_size; - fattr = dos_mode(conn,fsp->fsp_name,&sbuf); - mtime = convert_timespec_to_time_t(sbuf.st_ex_mtime); + size = smb_fname->st.st_ex_size; + fattr = dos_mode(conn,fsp->fsp_name,&smb_fname->st); + mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime); if (fattr & aDIR) { DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name)); close_file(req, fsp, ERROR_CLOSE); reply_doserror(req, ERRDOS,ERRnoaccess); - END_PROFILE(SMBopen); - return; + goto out; } reply_outbuf(req, 7, 0); @@ -1811,6 +1816,8 @@ void reply_open(struct smb_request *req) SCVAL(req->outbuf,smb_flg, CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED); } + out: + TALLOC_FREE(smb_fname); END_PROFILE(SMBopen); return; } @@ -1822,6 +1829,7 @@ void reply_open(struct smb_request *req) void reply_open_and_X(struct smb_request *req) { connection_struct *conn = req->conn; + struct smb_filename *smb_fname = NULL; char *fname = NULL; uint16 open_flags; int deny_mode; @@ -1838,7 +1846,6 @@ void reply_open_and_X(struct smb_request *req) int smb_ofun; uint32 fattr=0; int mtime=0; - SMB_STRUCT_STAT sbuf; int smb_action = 0; files_struct *fsp; NTSTATUS status; @@ -1854,12 +1861,9 @@ void reply_open_and_X(struct smb_request *req) if (req->wct < 15) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - END_PROFILE(SMBopenX); - return; + goto out; } - SET_STAT_INVALID(sbuf); - open_flags = SVAL(req->vwv+2, 0); deny_mode = SVAL(req->vwv+3, 0); smb_attr = SVAL(req->vwv+5, 0); @@ -1876,8 +1880,7 @@ void reply_open_and_X(struct smb_request *req) } else { reply_doserror(req, ERRSRV, ERRaccess); } - END_PROFILE(SMBopenX); - return; + goto out; } /* XXXX we need to handle passed times, sattr and flags */ @@ -1885,16 +1888,26 @@ void reply_open_and_X(struct smb_request *req) STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); - END_PROFILE(SMBopenX); - return; + goto out; } if (!map_open_params_to_ntcreate( fname, deny_mode, smb_ofun, &access_mask, &share_mode, &create_disposition, &create_options)) { reply_nterror(req, NT_STATUS_DOS(ERRDOS, ERRbadaccess)); - END_PROFILE(SMBopenX); - return; + goto out; + } + + status = unix_convert(ctx, conn, fname, &smb_fname, 0); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + goto out; + } + + status = get_full_smb_filename(ctx, smb_fname, &fname); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + goto out; } status = SMB_VFS_CREATE_FILE( @@ -1902,7 +1915,7 @@ void reply_open_and_X(struct smb_request *req) req, /* req */ 0, /* root_dir_fid */ fname, /* fname */ - CFF_DOS_PATH, /* create_file_flags */ + 0, /* create_file_flags */ access_mask, /* access_mask */ share_mode, /* share_access */ create_disposition, /* create_disposition*/ @@ -1914,16 +1927,15 @@ void reply_open_and_X(struct smb_request *req) NULL, /* ea_list */ &fsp, /* result */ &smb_action, /* pinfo */ - &sbuf); /* psbuf */ + &smb_fname->st); /* psbuf */ if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBopenX); if (open_was_deferred(req->mid)) { /* We have re-scheduled this call. */ - return; + goto out; } reply_openerror(req, status); - return; + goto out; } /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size, @@ -1933,26 +1945,24 @@ void reply_open_and_X(struct smb_request *req) if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) { close_file(req, fsp, ERROR_CLOSE); reply_nterror(req, NT_STATUS_DISK_FULL); - END_PROFILE(SMBopenX); - return; + goto out; } retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size); if (retval < 0) { close_file(req, fsp, ERROR_CLOSE); reply_nterror(req, NT_STATUS_DISK_FULL); - END_PROFILE(SMBopenX); - return; + goto out; } - sbuf.st_ex_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf); + smb_fname->st.st_ex_size = + SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st); } - fattr = dos_mode(conn,fsp->fsp_name,&sbuf); - mtime = convert_timespec_to_time_t(sbuf.st_ex_mtime); + fattr = dos_mode(conn,fsp->fsp_name,&smb_fname->st); + mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime); if (fattr & aDIR) { close_file(req, fsp, ERROR_CLOSE); reply_doserror(req, ERRDOS, ERRnoaccess); - END_PROFILE(SMBopenX); - return; + goto out; } /* If the caller set the extended oplock request bit @@ -1996,7 +2006,7 @@ void reply_open_and_X(struct smb_request *req) } else { srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime); } - SIVAL(req->outbuf,smb_vwv6,(uint32)sbuf.st_ex_size); + SIVAL(req->outbuf,smb_vwv6,(uint32)smb_fname->st.st_ex_size); SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode)); SSVAL(req->outbuf,smb_vwv11,smb_action); @@ -2004,8 +2014,10 @@ void reply_open_and_X(struct smb_request *req) SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS); } - END_PROFILE(SMBopenX); chain_reply(req); + out: + TALLOC_FREE(smb_fname); + END_PROFILE(SMBopenX); return; } @@ -2050,12 +2062,12 @@ void reply_ulogoffX(struct smb_request *req) void reply_mknew(struct smb_request *req) { connection_struct *conn = req->conn; + struct smb_filename *smb_fname = NULL; char *fname = NULL; uint32 fattr = 0; struct smb_file_time ft; files_struct *fsp; int oplock_request = 0; - SMB_STRUCT_STAT sbuf; NTSTATUS status; uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE; uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE; @@ -2065,12 +2077,10 @@ void reply_mknew(struct smb_request *req) START_PROFILE(SMBcreate); ZERO_STRUCT(ft); - SET_STAT_INVALID(sbuf); if (req->wct < 3) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - END_PROFILE(SMBcreate); - return; + goto out; } fattr = SVAL(req->vwv+0, 0); @@ -2083,8 +2093,7 @@ void reply_mknew(struct smb_request *req) STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); - END_PROFILE(SMBcreate); - return; + goto out; } if (fattr & aVOLID) { @@ -2100,12 +2109,24 @@ void reply_mknew(struct smb_request *req) create_disposition = FILE_OVERWRITE_IF; } + status = unix_convert(ctx, conn, fname, &smb_fname, 0); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + goto out; + } + + status = get_full_smb_filename(ctx, smb_fname, &fname); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + goto out; + } + status = SMB_VFS_CREATE_FILE( conn, /* conn */ req, /* req */ 0, /* root_dir_fid */ fname, /* fname */ - CFF_DOS_PATH, /* create_file_flags */ + 0, /* create_file_flags */ access_mask, /* access_mask */ share_mode, /* share_access */ create_disposition, /* create_disposition*/ @@ -2117,24 +2138,23 @@ void reply_mknew(struct smb_request *req) NULL, /* ea_list */ &fsp, /* result */ NULL, /* pinfo */ - &sbuf); /* psbuf */ + &smb_fname->st); /* psbuf */ if (!NT_STATUS_IS_OK(status)) { - END_PROFILE(SMBcreate); if (open_was_deferred(req->mid)) { /* We have re-scheduled this call. */ - return; + goto out; } reply_openerror(req, status); - return; + goto out; } - ft.atime = sbuf.st_ex_atime; /* atime. */ - status = smb_set_file_time(conn, fsp, fsp->fsp_name, &sbuf, &ft, true); + ft.atime = smb_fname->st.st_ex_atime; /* atime. */ + status = smb_set_file_time(conn, fsp, fsp->fsp_name, &smb_fname->st, + &ft, true); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBcreate); - reply_openerror(req, status); - return; + goto out; } reply_outbuf(req, 1, 0); @@ -2154,6 +2174,8 @@ void reply_mknew(struct smb_request *req) DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fsp->fsp_name, fsp->fh->fd, (unsigned int)fattr ) ); + out: + TALLOC_FREE(smb_fname); END_PROFILE(SMBcreate); return; } diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c index e264afab14..73c7cec63a 100644 --- a/source3/smbd/smb2_create.c +++ b/source3/smbd/smb2_create.c @@ -252,6 +252,7 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, files_struct *result; int info; SMB_STRUCT_STAT sbuf; + struct smb_filename *smb_fname = NULL; req = tevent_req_create(mem_ctx, &state, struct smbd_smb2_create_state); @@ -265,7 +266,7 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, smbreq = smbd_smb2_fake_smb_request(smb2req); if (tevent_req_nomem(smbreq, req)) { - return tevent_req_post(req, ev); + goto out; } if (IS_IPC(smbreq->conn)) { @@ -273,7 +274,7 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, if (!lp_nt_pipe_support()) { tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED); - return tevent_req_post(req, ev); + goto out; } /* Strip \\ off the name. */ @@ -284,7 +285,7 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, status = open_np_file(smbreq, pipe_name, &result); if (!NT_STATUS_IS_OK(status)) { tevent_req_nterror(req, status); - return tevent_req_post(req, ev); + goto out; } info = FILE_WAS_OPENED; ZERO_STRUCT(sbuf); @@ -292,7 +293,7 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, status = file_new(smbreq, smbreq->conn, &result); if(!NT_STATUS_IS_OK(status)) { tevent_req_nterror(req, status); - return tevent_req_post(req, ev); + goto out; } status = print_fsp_open(smbreq, @@ -304,19 +305,32 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, if (!NT_STATUS_IS_OK(status)) { file_free(smbreq, result); tevent_req_nterror(req, status); - return tevent_req_post(req, ev); + goto out; } info = FILE_WAS_CREATED; } else { + char *fname = NULL; + /* these are ignored for SMB2 */ in_create_options &= ~(0x10);/* NTCREATEX_OPTIONS_SYNC_ALERT */ in_create_options &= ~(0x20);/* NTCREATEX_OPTIONS_ASYNC_ALERT */ + status = unix_convert(talloc_tos(), smbreq->conn, in_name, + &smb_fname, 0); + if (!NT_STATUS_IS_OK(status)) { + goto out; + } + + status = get_full_smb_filename(talloc_tos(), smb_fname, &fname); + if (!NT_STATUS_IS_OK(status)) { + goto out; + } + status = SMB_VFS_CREATE_FILE(smbreq->conn, smbreq, 0, /* root_dir_fid */ - in_name, - CFF_DOS_PATH, /* create_file_flags */ + fname, + 0, /* create_file_flags */ in_desired_access, in_share_access, in_create_disposition, @@ -328,11 +342,12 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, NULL, /* ea_list */ &result, &info, - &sbuf); + &smb_fname->st); if (!NT_STATUS_IS_OK(status)) { tevent_req_nterror(req, status); - return tevent_req_post(req, ev); + goto out; } + sbuf = smb_fname->st; } smb2req->compat_chain_fsp = smbreq->chain_fsp; @@ -359,6 +374,8 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx, state->out_file_id_volatile = result->fnum; tevent_req_done(req); + out: + TALLOC_FREE(smb_fname); return tevent_req_post(req, ev); } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index a8120d42fb..a36e9f588a 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -869,6 +869,7 @@ static void call_trans2open(connection_struct *conn, char **ppdata, int total_data, unsigned int max_data_bytes) { + struct smb_filename *smb_fname = NULL; char *params = *pparams; char *pdata = *ppdata; int deny_mode; @@ -886,7 +887,6 @@ static void call_trans2open(connection_struct *conn, SMB_OFF_T size=0; int fattr=0,mtime=0; SMB_INO_T inode = 0; - SMB_STRUCT_STAT sbuf; int smb_action = 0; files_struct *fsp; struct ea_list *ea_list = NULL; @@ -898,15 +898,13 @@ static void call_trans2open(connection_struct *conn, uint32 create_options = 0; TALLOC_CTX *ctx = talloc_tos(); - SET_STAT_INVALID(sbuf); - /* * Ensure we have enough parameters to perform the operation. */ if (total_params < 29) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - return; + goto out; } flags = SVAL(params, 0); @@ -928,7 +926,7 @@ static void call_trans2open(connection_struct *conn, if (IS_IPC(conn)) { reply_doserror(req, ERRSRV, ERRaccess); - return; + goto out; } srvstr_get_path(ctx, params, req->flags2, &fname, pname, @@ -936,7 +934,7 @@ static void call_trans2open(connection_struct *conn, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); - return; + goto out; } DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n", @@ -945,7 +943,7 @@ static void call_trans2open(connection_struct *conn, if (open_ofun == 0) { reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION); - return; + goto out; } if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun, @@ -954,37 +952,49 @@ static void call_trans2open(connection_struct *conn, &create_disposition, &create_options)) { reply_doserror(req, ERRDOS, ERRbadaccess); - return; + goto out; } /* Any data in this call is an EA list. */ if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) { reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED); - return; + goto out; } if (total_data != 4) { if (total_data < 10) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - return; + goto out; } if (IVAL(pdata,0) > total_data) { DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n", IVAL(pdata,0), (unsigned int)total_data)); reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - return; + goto out; } ea_list = read_ea_list(talloc_tos(), pdata + 4, total_data - 4); if (!ea_list) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - return; + goto out; } } else if (IVAL(pdata,0) != 4) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - return; + goto out; + } + + status = unix_convert(ctx, conn, fname, &smb_fname, 0); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + goto out; + } + + status = get_full_smb_filename(ctx, smb_fname, &fname); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + goto out; } status = SMB_VFS_CREATE_FILE( @@ -992,7 +1002,7 @@ static void call_trans2open(connection_struct *conn, req, /* req */ 0, /* root_dir_fid */ fname, /* fname */ - CFF_DOS_PATH, /* create_file_flags */ + 0, /* create_file_flags */ access_mask, /* access_mask */ share_mode, /* share_access */ create_disposition, /* create_disposition*/ @@ -1004,32 +1014,32 @@ static void call_trans2open(connection_struct *conn, ea_list, /* ea_list */ &fsp, /* result */ &smb_action, /* pinfo */ - &sbuf); /* psbuf */ + &smb_fname->st); /* psbuf */ if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(req->mid)) { /* We have re-scheduled this call. */ - return; + goto out; } reply_openerror(req, status); - return; + goto out; } - size = get_file_size_stat(&sbuf); - fattr = dos_mode(conn,fsp->fsp_name,&sbuf); - mtime = convert_timespec_to_time_t(sbuf.st_ex_mtime); - inode = sbuf.st_ex_ino; + size = get_file_size_stat(&smb_fname->st); + fattr = dos_mode(conn, fsp->fsp_name, &smb_fname->st); + mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime); + inode = smb_fname->st.st_ex_ino; if (fattr & aDIR) { close_file(req, fsp, ERROR_CLOSE); reply_doserror(req, ERRDOS,ERRnoaccess); - return; + goto out; } /* Realloc the size of parameters and data we will return */ *pparams = (char *)SMB_REALLOC(*pparams, 30); if(*pparams == NULL ) { reply_nterror(req, NT_STATUS_NO_MEMORY); - return; + goto out; } params = *pparams; @@ -1061,6 +1071,8 @@ static void call_trans2open(connection_struct *conn, /* Send the required number of replies */ send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes); + out: + TALLOC_FREE(smb_fname); } /********************************************************* -- cgit