From: Volker Lendecke Date: Fri, 23 Dec 2022 17:20:15 +0000 (+0100) Subject: smbd: Simplify call_trans2qfilepathinfo() X-Git-Tag: talloc-2.4.0~104 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5f7d16dbefaf26abe161ed32b7383c0bb1e2e7bb;p=thirdparty%2Fsamba.git smbd: Simplify call_trans2qfilepathinfo() Move the file/path specific preparations to the respective callers. Signed-off-by: Volker Lendecke Reviewed-by: Ralph Boehme --- diff --git a/source3/smbd/smb1_trans2.c b/source3/smbd/smb1_trans2.c index 0d7ffebd024..3b10934f565 100644 --- a/source3/smbd/smb1_trans2.c +++ b/source3/smbd/smb1_trans2.c @@ -1933,287 +1933,24 @@ static void call_trans2qpipeinfo(connection_struct *conn, static void call_trans2qfilepathinfo(connection_struct *conn, struct smb_request *req, unsigned int tran_call, + uint16_t info_level, + struct smb_filename *smb_fname, + struct files_struct *fsp, + bool delete_pending, + struct timespec write_time_ts, char **pparams, int total_params, char **ppdata, int total_data, unsigned int max_data_bytes) { char *params = *pparams; char *pdata = *ppdata; - uint16_t info_level; unsigned int data_size = 0; unsigned int param_size = 2; - struct smb_filename *smb_fname = NULL; - bool delete_pending = False; - struct timespec write_time_ts; - struct files_struct *dirfsp = NULL; - files_struct *fsp = NULL; - struct file_id fileid; struct ea_list *ea_list = NULL; int lock_data_count = 0; char *lock_data = NULL; size_t fixed_portion; NTSTATUS status = NT_STATUS_OK; - int ret; - - if (!params) { - reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - return; - } - - ZERO_STRUCT(write_time_ts); - - if (tran_call == TRANSACT2_QFILEINFO) { - if (total_params < 4) { - reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - return; - } - - fsp = file_fsp(req, SVAL(params,0)); - info_level = SVAL(params,2); - - if (IS_IPC(conn)) { - call_trans2qpipeinfo( - conn, - req, - fsp, - info_level, - tran_call, - pparams, - total_params, - ppdata, - total_data, - max_data_bytes); - return; - } - - DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level)); - - if (INFO_LEVEL_IS_UNIX(info_level)) { - if (!lp_smb1_unix_extensions()) { - reply_nterror(req, NT_STATUS_INVALID_LEVEL); - return; - } - if (!req->posix_pathnames) { - reply_nterror(req, NT_STATUS_INVALID_LEVEL); - return; - } - } - - /* Initial check for valid fsp ptr. */ - if (!check_fsp_open(conn, req, fsp)) { - return; - } - - smb_fname = fsp->fsp_name; - - if(fsp->fake_file_handle) { - /* - * This is actually for the QUOTA_FAKE_FILE --metze - */ - - /* We know this name is ok, it's already passed the checks. */ - - } else if(fsp_get_pathref_fd(fsp) == -1) { - /* - * This is actually a QFILEINFO on a directory - * handle (returned from an NT SMB). NT5.0 seems - * to do this call. JRA. - */ - ret = vfs_stat(conn, smb_fname); - if (ret != 0) { - DBG_NOTICE("vfs_stat of %s failed (%s)\n", - smb_fname_str_dbg(smb_fname), - strerror(errno)); - reply_nterror(req, - map_nt_error_from_unix(errno)); - return; - } - - if (fsp_getinfo_ask_sharemode(fsp)) { - fileid = vfs_file_id_from_sbuf( - conn, &smb_fname->st); - get_file_infos(fileid, fsp->name_hash, - &delete_pending, - &write_time_ts); - } - } else { - /* - * Original code - this is an open file. - */ - status = vfs_stat_fsp(fsp); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(3, ("fstat of %s failed (%s)\n", - fsp_fnum_dbg(fsp), nt_errstr(status))); - reply_nterror(req, status); - return; - } - if (fsp_getinfo_ask_sharemode(fsp)) { - fileid = vfs_file_id_from_sbuf( - conn, &smb_fname->st); - get_file_infos(fileid, fsp->name_hash, - &delete_pending, - &write_time_ts); - } - } - - } else { - uint32_t name_hash; - char *fname = NULL; - uint32_t ucf_flags = ucf_flags_from_smb_request(req); - NTTIME twrp = 0; - - /* qpathinfo */ - if (total_params < 7) { - reply_nterror(req, NT_STATUS_INVALID_PARAMETER); - return; - } - - info_level = SVAL(params,0); - - DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level)); - - if (INFO_LEVEL_IS_UNIX(info_level)) { - if (!lp_smb1_unix_extensions()) { - reply_nterror(req, NT_STATUS_INVALID_LEVEL); - return; - } - if (!req->posix_pathnames) { - reply_nterror(req, NT_STATUS_INVALID_LEVEL); - return; - } - } - - if (req->posix_pathnames) { - srvstr_get_path_posix(req, - params, - req->flags2, - &fname, - ¶ms[6], - total_params - 6, - STR_TERMINATE, - &status); - } else { - srvstr_get_path(req, - params, - req->flags2, - &fname, - ¶ms[6], - total_params - 6, - STR_TERMINATE, - &status); - } - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - return; - } - - if (ucf_flags & UCF_GMT_PATHNAME) { - extract_snapshot_token(fname, &twrp); - } - status = filename_convert_dirfsp(req, - conn, - fname, - ucf_flags, - twrp, - &dirfsp, - &smb_fname); - if (!NT_STATUS_IS_OK(status)) { - if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { - reply_botherror(req, - NT_STATUS_PATH_NOT_COVERED, - ERRSRV, ERRbadpath); - return; - } - reply_nterror(req, status); - return; - } - - /* - * qpathinfo must operate on an existing file, so we - * can exit early if filename_convert_dirfsp() returned the - * "new file" NT_STATUS_OK, !VALID_STAT case. - */ - - if (!VALID_STAT(smb_fname->st)) { - reply_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND); - return; - } - - /* - * smb_fname->fsp may be NULL if smb_fname points at a symlink - * and we're in POSIX context, so be careful when using fsp - * below, it can still be NULL. - */ - fsp = smb_fname->fsp; - - /* If this is a stream, check if there is a delete_pending. */ - if ((conn->fs_capabilities & FILE_NAMED_STREAMS) - && is_ntfs_stream_smb_fname(smb_fname)) { - struct smb_filename *smb_fname_base; - - /* Create an smb_filename with stream_name == NULL. */ - smb_fname_base = synthetic_smb_fname( - talloc_tos(), - smb_fname->base_name, - NULL, - NULL, - smb_fname->twrp, - smb_fname->flags); - if (smb_fname_base == NULL) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - return; - } - - ret = vfs_stat(conn, smb_fname_base); - if (ret != 0) { - DBG_NOTICE("vfs_stat of %s failed " - "(%s)\n", - smb_fname_str_dbg(smb_fname_base), - strerror(errno)); - TALLOC_FREE(smb_fname_base); - reply_nterror(req, - map_nt_error_from_unix(errno)); - return; - } - - status = file_name_hash(conn, - smb_fname_str_dbg(smb_fname_base), - &name_hash); - if (!NT_STATUS_IS_OK(status)) { - TALLOC_FREE(smb_fname_base); - reply_nterror(req, status); - return; - } - - fileid = vfs_file_id_from_sbuf(conn, - &smb_fname_base->st); - TALLOC_FREE(smb_fname_base); - get_file_infos(fileid, name_hash, &delete_pending, NULL); - if (delete_pending) { - reply_nterror(req, NT_STATUS_DELETE_PENDING); - return; - } - } - - status = file_name_hash(conn, - smb_fname_str_dbg(smb_fname), - &name_hash); - if (!NT_STATUS_IS_OK(status)) { - reply_nterror(req, status); - return; - } - - if (fsp_getinfo_ask_sharemode(fsp)) { - fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st); - get_file_infos(fileid, name_hash, &delete_pending, - &write_time_ts); - } - - if (delete_pending) { - reply_nterror(req, NT_STATUS_DELETE_PENDING); - return; - } - } DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d " "total_data=%d\n", smb_fname_str_dbg(smb_fname), @@ -2364,10 +2101,188 @@ static void call_trans2qpathinfo( int total_data, unsigned int max_data_bytes) { + char *params = *pparams; + uint16_t info_level; + struct smb_filename *smb_fname = NULL; + bool delete_pending = False; + struct timespec write_time_ts = { .tv_sec = 0, }; + struct files_struct *dirfsp = NULL; + files_struct *fsp = NULL; + struct file_id fileid; + uint32_t name_hash; + char *fname = NULL; + uint32_t ucf_flags = ucf_flags_from_smb_request(req); + NTTIME twrp = 0; + NTSTATUS status = NT_STATUS_OK; + int ret; + + if (!params) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; + } + + + /* qpathinfo */ + if (total_params < 7) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; + } + + info_level = SVAL(params,0); + + DBG_NOTICE("TRANSACT2_QPATHINFO: level = %d\n", info_level); + + if (INFO_LEVEL_IS_UNIX(info_level)) { + if (!lp_smb1_unix_extensions()) { + reply_nterror(req, NT_STATUS_INVALID_LEVEL); + return; + } + if (!req->posix_pathnames) { + reply_nterror(req, NT_STATUS_INVALID_LEVEL); + return; + } + } + + if (req->posix_pathnames) { + srvstr_get_path_posix(req, + params, + req->flags2, + &fname, + ¶ms[6], + total_params - 6, + STR_TERMINATE, + &status); + } else { + srvstr_get_path(req, + params, + req->flags2, + &fname, + ¶ms[6], + total_params - 6, + STR_TERMINATE, + &status); + } + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + return; + } + + if (ucf_flags & UCF_GMT_PATHNAME) { + extract_snapshot_token(fname, &twrp); + } + status = filename_convert_dirfsp(req, + conn, + fname, + ucf_flags, + twrp, + &dirfsp, + &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) { + reply_botherror(req, + NT_STATUS_PATH_NOT_COVERED, + ERRSRV, ERRbadpath); + return; + } + reply_nterror(req, status); + return; + } + + /* + * qpathinfo must operate on an existing file, so we + * can exit early if filename_convert_dirfsp() returned the + * "new file" NT_STATUS_OK, !VALID_STAT case. + */ + + if (!VALID_STAT(smb_fname->st)) { + reply_nterror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND); + return; + } + + /* + * smb_fname->fsp may be NULL if smb_fname points at a symlink + * and we're in POSIX context, so be careful when using fsp + * below, it can still be NULL. + */ + fsp = smb_fname->fsp; + + /* If this is a stream, check if there is a delete_pending. */ + if ((conn->fs_capabilities & FILE_NAMED_STREAMS) + && is_ntfs_stream_smb_fname(smb_fname)) { + struct smb_filename *smb_fname_base; + + /* Create an smb_filename with stream_name == NULL. */ + smb_fname_base = synthetic_smb_fname( + talloc_tos(), + smb_fname->base_name, + NULL, + NULL, + smb_fname->twrp, + smb_fname->flags); + if (smb_fname_base == NULL) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + return; + } + + ret = vfs_stat(conn, smb_fname_base); + if (ret != 0) { + DBG_NOTICE("vfs_stat of %s failed " + "(%s)\n", + smb_fname_str_dbg(smb_fname_base), + strerror(errno)); + TALLOC_FREE(smb_fname_base); + reply_nterror(req, + map_nt_error_from_unix(errno)); + return; + } + + status = file_name_hash(conn, + smb_fname_str_dbg(smb_fname_base), + &name_hash); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(smb_fname_base); + reply_nterror(req, status); + return; + } + + fileid = vfs_file_id_from_sbuf(conn, + &smb_fname_base->st); + TALLOC_FREE(smb_fname_base); + get_file_infos(fileid, name_hash, &delete_pending, NULL); + if (delete_pending) { + reply_nterror(req, NT_STATUS_DELETE_PENDING); + return; + } + } + + status = file_name_hash(conn, + smb_fname_str_dbg(smb_fname), + &name_hash); + if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); + return; + } + + if (fsp_getinfo_ask_sharemode(fsp)) { + fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st); + get_file_infos(fileid, name_hash, &delete_pending, + &write_time_ts); + } + + if (delete_pending) { + reply_nterror(req, NT_STATUS_DELETE_PENDING); + return; + } + call_trans2qfilepathinfo( conn, req, TRANSACT2_QPATHINFO, + info_level, + smb_fname, + fsp, + false, + write_time_ts, pparams, total_params, ppdata, @@ -2384,10 +2299,123 @@ static void call_trans2qfileinfo( int total_data, unsigned int max_data_bytes) { + char *params = *pparams; + uint16_t info_level; + struct smb_filename *smb_fname = NULL; + bool delete_pending = False; + struct timespec write_time_ts = { .tv_sec = 0, }; + files_struct *fsp = NULL; + struct file_id fileid; + NTSTATUS status = NT_STATUS_OK; + int ret; + + if (params == NULL) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; + } + + if (total_params < 4) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + return; + } + + fsp = file_fsp(req, SVAL(params,0)); + info_level = SVAL(params,2); + + if (IS_IPC(conn)) { + call_trans2qpipeinfo( + conn, + req, + fsp, + info_level, + TRANSACT2_QFILEINFO, + pparams, + total_params, + ppdata, + total_data, + max_data_bytes); + return; + } + + DBG_NOTICE("TRANSACT2_QFILEINFO: level = %d\n", info_level); + + if (INFO_LEVEL_IS_UNIX(info_level)) { + if (!lp_smb1_unix_extensions()) { + reply_nterror(req, NT_STATUS_INVALID_LEVEL); + return; + } + if (!req->posix_pathnames) { + reply_nterror(req, NT_STATUS_INVALID_LEVEL); + return; + } + } + + /* Initial check for valid fsp ptr. */ + if (!check_fsp_open(conn, req, fsp)) { + return; + } + + smb_fname = fsp->fsp_name; + + if(fsp->fake_file_handle) { + /* + * This is actually for the QUOTA_FAKE_FILE --metze + */ + + /* We know this name is ok, it's already passed the checks. */ + + } else if(fsp_get_pathref_fd(fsp) == -1) { + /* + * This is actually a QFILEINFO on a directory + * handle (returned from an NT SMB). NT5.0 seems + * to do this call. JRA. + */ + ret = vfs_stat(conn, smb_fname); + if (ret != 0) { + DBG_NOTICE("vfs_stat of %s failed (%s)\n", + smb_fname_str_dbg(smb_fname), + strerror(errno)); + reply_nterror(req, + map_nt_error_from_unix(errno)); + return; + } + + if (fsp_getinfo_ask_sharemode(fsp)) { + fileid = vfs_file_id_from_sbuf( + conn, &smb_fname->st); + get_file_infos(fileid, fsp->name_hash, + &delete_pending, + &write_time_ts); + } + } else { + /* + * Original code - this is an open file. + */ + status = vfs_stat_fsp(fsp); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(3, ("fstat of %s failed (%s)\n", + fsp_fnum_dbg(fsp), nt_errstr(status))); + reply_nterror(req, status); + return; + } + if (fsp_getinfo_ask_sharemode(fsp)) { + fileid = vfs_file_id_from_sbuf( + conn, &smb_fname->st); + get_file_infos(fileid, fsp->name_hash, + &delete_pending, + &write_time_ts); + } + } + call_trans2qfilepathinfo( conn, req, TRANSACT2_QFILEINFO, + info_level, + smb_fname, + fsp, + delete_pending, + write_time_ts, pparams, total_params, ppdata,