#include "../libcli/auth/libcli_auth.h"
#include "../librpc/gen_ndr/xattr.h"
#include "../librpc/gen_ndr/ndr_security.h"
-#include "../librpc/gen_ndr/open_files.h"
#include "libcli/security/security.h"
#include "trans2.h"
#include "auth.h"
#include "printing.h"
#include "lib/util_ea.h"
#include "lib/readdir_attr.h"
+#include "messages.h"
#define DIR_ENTRY_SAFETY_MARGIN 4096
files_struct *fsp,
const SMB_STRUCT_STAT *psbuf);
+/****************************************************************************
+ Check if an open file handle or smb_fname is a symlink.
+****************************************************************************/
+
+static NTSTATUS refuse_symlink(connection_struct *conn,
+ const files_struct *fsp,
+ const struct smb_filename *smb_fname)
+{
+ SMB_STRUCT_STAT sbuf;
+ const SMB_STRUCT_STAT *pst = NULL;
+
+ if (fsp) {
+ pst = &fsp->fsp_name->st;
+ } else {
+ pst = &smb_fname->st;
+ }
+
+ if (!VALID_STAT(*pst)) {
+ int ret = vfs_stat_smb_basename(conn,
+ smb_fname,
+ &sbuf);
+ if (ret == -1 && errno != ENOENT) {
+ return map_nt_error_from_unix(errno);
+ } else if (ret == -1) {
+ /* it's not a symlink.. */
+ return NT_STATUS_OK;
+ }
+ pst = &sbuf;
+ }
+
+ if (S_ISLNK(pst->st_ex_mode)) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ return NT_STATUS_OK;
+}
+
NTSTATUS check_access_fsp(const struct files_struct *fsp,
uint32_t access_mask)
{
uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
{
uint64_t file_index;
+ if (conn->sconn->aapl_zero_file_id) {
+ return 0;
+ }
if (conn->base_share_dev == psbuf->st_ex_dev) {
return (uint64_t)psbuf->st_ex_ino;
}
return file_index;
}
+
+/********************************************************************
+ Globally (for this connection / multi-channel) disable file-ID
+ calculation. This is required to be global because it serves
+ Macs in AAPL mode, which is globally set.
+********************************************************************/
+void aapl_force_zero_file_id(struct smbd_server_connection *sconn)
+{
+ sconn->aapl_zero_file_id = true;
+}
+
/****************************************************************************
Utility functions for dealing with extended attributes.
****************************************************************************/
Get one EA value. Fill in a struct ea_struct.
****************************************************************************/
-NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
- files_struct *fsp, const char *fname,
- const char *ea_name, struct ea_struct *pea)
+NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx,
+ connection_struct *conn,
+ files_struct *fsp,
+ const struct smb_filename *smb_fname,
+ const char *ea_name,
+ struct ea_struct *pea)
{
/* Get the value of this xattr. Max size is 64k. */
size_t attr_size = 256;
if (fsp && fsp->fh->fd != -1) {
sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
} else {
- sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
+ sizeret = SMB_VFS_GETXATTR(conn, smb_fname,
+ ea_name, val, attr_size);
}
if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
return NT_STATUS_OK;
}
-NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
- files_struct *fsp, const char *fname,
- char ***pnames, size_t *pnum_names)
+NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx,
+ connection_struct *conn,
+ files_struct *fsp,
+ const struct smb_filename *smb_fname,
+ char ***pnames,
+ size_t *pnum_names)
{
+ char smallbuf[1024];
/* Get a list of all xattrs. Max namesize is 64k. */
size_t ea_namelist_size = 1024;
- char *ea_namelist = NULL;
+ char *ea_namelist = smallbuf;
+ char *to_free = NULL;
char *p;
- char **names, **tmp;
+ char **names;
size_t num_names;
ssize_t sizeret = -1;
+ NTSTATUS status;
- if (!lp_ea_support(SNUM(conn))) {
- if (pnames) {
- *pnames = NULL;
- }
- *pnum_names = 0;
- return NT_STATUS_OK;
+ if (pnames) {
+ *pnames = NULL;
}
+ *pnum_names = 0;
- /*
- * TALLOC the result early to get the talloc hierarchy right.
- */
-
- names = talloc_array(mem_ctx, char *, 1);
- if (names == NULL) {
- DEBUG(0, ("talloc failed\n"));
- return NT_STATUS_NO_MEMORY;
+ status = refuse_symlink(conn, fsp, smb_fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ /*
+ * Just return no EA's on a symlink.
+ */
+ return NT_STATUS_OK;
}
- while (ea_namelist_size <= 65536) {
+ if (fsp && fsp->fh->fd != -1) {
+ sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
+ ea_namelist_size);
+ } else {
+ sizeret = SMB_VFS_LISTXATTR(conn,
+ smb_fname,
+ ea_namelist,
+ ea_namelist_size);
+ }
- ea_namelist = talloc_realloc(
- names, ea_namelist, char, ea_namelist_size);
+ if ((sizeret == -1) && (errno == ERANGE)) {
+ ea_namelist_size = 65536;
+ ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
if (ea_namelist == NULL) {
- DEBUG(0, ("talloc failed\n"));
- TALLOC_FREE(names);
return NT_STATUS_NO_MEMORY;
}
+ to_free = ea_namelist;
if (fsp && fsp->fh->fd != -1) {
sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
ea_namelist_size);
} else {
- sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
+ sizeret = SMB_VFS_LISTXATTR(conn,
+ smb_fname,
+ ea_namelist,
ea_namelist_size);
}
-
- if ((sizeret == -1) && (errno == ERANGE)) {
- ea_namelist_size *= 2;
- }
- else {
- break;
- }
}
if (sizeret == -1) {
- TALLOC_FREE(names);
- return map_nt_error_from_unix(errno);
+ status = map_nt_error_from_unix(errno);
+ TALLOC_FREE(to_free);
+ return status;
}
- DEBUG(10, ("%s: ea_namelist size = %u\n",
- __func__, (unsigned int)sizeret));
+ DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
if (sizeret == 0) {
- TALLOC_FREE(names);
- if (pnames) {
- *pnames = NULL;
- }
- *pnum_names = 0;
+ TALLOC_FREE(to_free);
return NT_STATUS_OK;
}
*/
if (ea_namelist[sizeret-1] != '\0') {
- TALLOC_FREE(names);
+ TALLOC_FREE(to_free);
return NT_STATUS_INTERNAL_ERROR;
}
num_names += 1;
}
- tmp = talloc_realloc(mem_ctx, names, char *, num_names);
- if (tmp == NULL) {
+ *pnum_names = num_names;
+
+ if (pnames == NULL) {
+ TALLOC_FREE(to_free);
+ return NT_STATUS_OK;
+ }
+
+ names = talloc_array(mem_ctx, char *, num_names);
+ if (names == NULL) {
DEBUG(0, ("talloc failed\n"));
- TALLOC_FREE(names);
+ TALLOC_FREE(to_free);
return NT_STATUS_NO_MEMORY;
}
- names = tmp;
+ if (ea_namelist == smallbuf) {
+ ea_namelist = talloc_memdup(names, smallbuf, sizeret);
+ if (ea_namelist == NULL) {
+ TALLOC_FREE(names);
+ return NT_STATUS_NO_MEMORY;
+ }
+ } else {
+ talloc_steal(names, ea_namelist);
+
+ ea_namelist = talloc_realloc(names, ea_namelist, char,
+ sizeret);
+ if (ea_namelist == NULL) {
+ TALLOC_FREE(names);
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+
num_names = 0;
for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
names[num_names++] = p;
}
- if (pnames) {
- *pnames = names;
- } else {
- TALLOC_FREE(names);
- }
- *pnum_names = num_names;
+ *pnames = names;
+
return NT_STATUS_OK;
}
Return a linked list of the total EA's. Plus the total size
****************************************************************************/
-static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
- const char *fname, size_t *pea_total_len, struct ea_list **ea_list)
+static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx,
+ connection_struct *conn,
+ files_struct *fsp,
+ const struct smb_filename *smb_fname,
+ size_t *pea_total_len,
+ struct ea_list **ea_list)
{
/* Get a list of all xattrs. Max namesize is 64k. */
size_t i, num_names;
char **names;
struct ea_list *ea_list_head = NULL;
+ bool posix_pathnames = false;
NTSTATUS status;
*pea_total_len = 0;
*ea_list = NULL;
- status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
- &names, &num_names);
+ if (!lp_ea_support(SNUM(conn))) {
+ return NT_STATUS_OK;
+ }
+
+ if (fsp) {
+ posix_pathnames =
+ (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
+ } else {
+ posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
+ }
+
+ status = get_ea_names_from_file(talloc_tos(),
+ conn,
+ fsp,
+ smb_fname,
+ &names,
+ &num_names);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
if (num_names == 0) {
- *ea_list = NULL;
return NT_STATUS_OK;
}
* Filter out any underlying POSIX EA names
* that a Windows client can't handle.
*/
- if (!lp_posix_pathnames() &&
+ if (!posix_pathnames &&
is_invalid_windows_ea_name(names[i])) {
continue;
}
return NT_STATUS_NO_MEMORY;
}
- status = get_ea_value(listp, conn, fsp,
- fname, names[i],
- &listp->ea);
+ status = get_ea_value(listp,
+ conn,
+ fsp,
+ smb_fname,
+ names[i],
+ &listp->ea);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(listp);
"= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
(unsigned int)listp->ea.value.length));
- DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
+ DLIST_ADD_END(ea_list_head, listp);
}
return NT_STATUS_INVALID_PARAMETER;
}
- return get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, pea_total_len, ea_list);
+ return get_ea_list_from_file_path(mem_ctx,
+ conn,
+ fsp,
+ smb_fname,
+ pea_total_len,
+ ea_list);
}
/****************************************************************************
if (is_ntfs_stream_smb_fname(smb_fname)) {
fsp = NULL;
}
- (void)get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, &total_ea_len, &ea_list);
+ (void)get_ea_list_from_file_path(mem_ctx,
+ conn,
+ fsp,
+ smb_fname,
+ &total_ea_len,
+ &ea_list);
if(conn->sconn->using_smb2) {
NTSTATUS status;
unsigned int ret_data_size;
Ensure the EA name is case insensitive by matching any existing EA name.
****************************************************************************/
-static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
+static void canonicalize_ea_name(connection_struct *conn,
+ files_struct *fsp,
+ const struct smb_filename *smb_fname,
+ fstring unix_ea_name)
{
size_t total_ea_len;
TALLOC_CTX *mem_ctx = talloc_tos();
struct ea_list *ea_list;
- NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
+ NTSTATUS status = get_ea_list_from_file_path(mem_ctx,
+ conn,
+ fsp,
+ smb_fname,
+ &total_ea_len,
+ &ea_list);
if (!NT_STATUS_IS_OK(status)) {
return;
}
const struct smb_filename *smb_fname, struct ea_list *ea_list)
{
NTSTATUS status;
- char *fname = NULL;
+ bool posix_pathnames = false;
if (!lp_ea_support(SNUM(conn))) {
return NT_STATUS_EAS_NOT_SUPPORTED;
}
+ if (fsp) {
+ posix_pathnames =
+ (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
+ } else {
+ posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
+ }
+
+ status = refuse_symlink(conn, fsp, smb_fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
if (!NT_STATUS_IS_OK(status)) {
return status;
* we set *any* of them.
*/
- if (ea_list_has_invalid_name(ea_list)) {
+ if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
return STATUS_INVALID_EA_NAME;
}
- fname = smb_fname->base_name;
-
for (;ea_list; ea_list = ea_list->next) {
int ret;
fstring unix_ea_name;
fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
fstrcat(unix_ea_name, ea_list->ea.name);
- canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
+ canonicalize_ea_name(conn,
+ fsp,
+ smb_fname,
+ unix_ea_name);
DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
} else {
DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
- unix_ea_name, fname));
- ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
+ unix_ea_name, smb_fname->base_name));
+ ret = SMB_VFS_REMOVEXATTR(conn,
+ smb_fname,
+ unix_ea_name);
}
#ifdef ENOATTR
/* Removing a non existent attribute always succeeds. */
ea_list->ea.value.data, ea_list->ea.value.length, 0);
} else {
DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
- unix_ea_name, fname));
- ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
- ea_list->ea.value.data, ea_list->ea.value.length, 0);
+ unix_ea_name, smb_fname->base_name));
+ ret = SMB_VFS_SETXATTR(conn,
+ smb_fname,
+ unix_ea_name,
+ ea_list->ea.value.data,
+ ea_list->ea.value.length,
+ 0);
}
}
}
offset += (namelen + 1); /* Go past the name + terminating zero. */
- DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
+ DLIST_ADD_END(ea_list_head, eal);
DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
}
return NULL;
}
- DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
+ DLIST_ADD_END(ea_list_head, eal);
offset += bytes_used;
}
uint32_t create_disposition;
uint32_t create_options = 0;
uint32_t private_flags = 0;
- uint32_t ucf_flags = (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
+ uint32_t ucf_flags = ucf_flags_from_smb_request(req);
TALLOC_CTX *ctx = talloc_tos();
/*
goto out;
}
- srvstr_get_path(ctx, params, req->flags2, &fname, pname,
- total_params - 28, STR_TERMINATE,
+ if (req->posix_pathnames) {
+ srvstr_get_path_posix(ctx,
+ params,
+ req->flags2,
+ &fname,
+ pname,
+ total_params - 28,
+ STR_TERMINATE,
+ &status);
+ } else {
+ srvstr_get_path(ctx,
+ params,
+ req->flags2,
+ &fname,
+ pname,
+ total_params - 28,
+ STR_TERMINATE,
&status);
+ }
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
goto out;
status = filename_convert(ctx,
conn,
- req->flags2 & FLAGS2_DFS_PATHNAMES,
fname,
ucf_flags,
NULL,
goto out;
}
- if (ea_list_has_invalid_name(ea_list)) {
+ if (!req->posix_pathnames &&
+ ea_list_has_invalid_name(ea_list)) {
int param_len = 30;
*pparams = (char *)SMB_REALLOC(*pparams, param_len);
if(*pparams == NULL ) {
****************************************************************************/
static bool check_msdfs_link(connection_struct *conn,
- const char *pathname,
- SMB_STRUCT_STAT *psbuf)
+ struct smb_filename *smb_fname)
{
int saved_errno = errno;
if(lp_host_msdfs() &&
lp_msdfs_root(SNUM(conn)) &&
- is_msdfs_link(conn, pathname, psbuf)) {
+ is_msdfs_link(conn, smb_fname)) {
DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
"as a directory\n",
- pathname));
- psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
+ smb_fname->base_name));
+ smb_fname->st.st_ex_mode =
+ (smb_fname->st.st_ex_mode & 0xFFF) | S_IFDIR;
errno = saved_errno;
return true;
}
static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
void *private_data,
struct smb_filename *smb_fname,
+ bool get_dosmode,
uint32_t *_mode)
{
struct smbd_dirptr_lanman2_state *state =
* directories */
ms_dfs_link = check_msdfs_link(state->conn,
- smb_fname->base_name,
- &smb_fname->st);
+ smb_fname);
if (!ms_dfs_link) {
DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
"Couldn't stat [%s] (%s)\n",
if (ms_dfs_link) {
mode = dos_mode_msdfs(state->conn, smb_fname);
- } else {
+ } else if (get_dosmode) {
mode = dos_mode(state->conn, smb_fname);
}
int requires_resume_key,
bool dont_descend,
bool ask_sharemode,
+ bool get_dosmode,
uint8_t align,
bool do_pad,
char **ppdata,
char *base_data,
char *end_data,
int space_remaining,
+ struct smb_filename **_smb_fname,
bool *got_exact_match,
int *_last_entry_off,
- struct ea_list *name_list)
+ struct ea_list *name_list,
+ struct file_id *file_id)
{
const char *p;
const char *mask = NULL;
bool ok;
uint64_t last_entry_off = 0;
NTSTATUS status;
+ enum mangled_names_options mangled_names;
+ bool marshall_with_83_names;
+
+ mangled_names = lp_mangled_names(conn->params);
ZERO_STRUCT(state);
state.conn = conn;
state.info_level = info_level;
- state.check_mangled_names = lp_mangled_names(conn->params);
+ if (mangled_names != MANGLED_NAMES_NO) {
+ state.check_mangled_names = true;
+ }
state.has_wild = dptr_has_wild(dirptr);
state.got_exact_match = false;
dirtype,
dont_descend,
ask_sharemode,
+ get_dosmode,
smbd_dirptr_lanman2_match_fn,
smbd_dirptr_lanman2_mode_fn,
&state,
*got_exact_match = state.got_exact_match;
+ marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
+
status = smbd_marshall_dir_entry(ctx,
conn,
flags2,
info_level,
name_list,
- state.check_mangled_names,
+ marshall_with_83_names,
requires_resume_key,
mode,
fname,
DEBUG(1,("Conversion error: illegal character: %s\n",
smb_fname_str_dbg(smb_fname)));
}
- TALLOC_FREE(fname);
+
+ if (file_id != NULL) {
+ *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
+ }
+
+ if (!NT_STATUS_IS_OK(status) &&
+ !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
+ {
+ TALLOC_FREE(smb_fname);
+ TALLOC_FREE(fname);
+ return status;
+ }
+
+ if (_smb_fname != NULL) {
+ struct smb_filename *name = NULL;
+
+ name = synthetic_smb_fname(ctx, fname, NULL, &smb_fname->st, 0);
+ if (name == NULL) {
+ TALLOC_FREE(smb_fname);
+ TALLOC_FREE(fname);
+ return NT_STATUS_NO_MEMORY;
+ }
+ *_smb_fname = name;
+ }
+
TALLOC_FREE(smb_fname);
+ TALLOC_FREE(fname);
+
if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
dptr_SeekDir(dirptr, prev_dirpos);
return status;
}
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
*_last_entry_off = last_entry_off;
return NT_STATUS_OK;
return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
path_mask, dirtype, info_level,
requires_resume_key, dont_descend, ask_sharemode,
- align, do_pad,
+ true, align, do_pad,
ppdata, base_data, end_data,
space_remaining,
+ NULL,
got_exact_match,
- last_entry_off, name_list);
+ last_entry_off, name_list, NULL);
}
/****************************************************************************
struct ea_list *ea_list = NULL;
NTSTATUS ntstatus = NT_STATUS_OK;
bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
- TALLOC_CTX *ctx = talloc_tos();
struct dptr_struct *dirptr = NULL;
struct smbd_server_connection *sconn = req->sconn;
uint32_t ucf_flags = UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP |
- (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
+ ucf_flags_from_smb_request(req);
bool backup_priv = false;
bool as_root = false;
goto out;
}
- srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
- params+12, total_params - 12,
- STR_TERMINATE, &ntstatus, &mask_contains_wcard);
+ if (req->posix_pathnames) {
+ srvstr_get_path_wcard_posix(talloc_tos(),
+ params,
+ req->flags2,
+ &directory,
+ params+12,
+ total_params - 12,
+ STR_TERMINATE,
+ &ntstatus,
+ &mask_contains_wcard);
+ } else {
+ srvstr_get_path_wcard(talloc_tos(),
+ params,
+ req->flags2,
+ &directory,
+ params+12,
+ total_params - 12,
+ STR_TERMINATE,
+ &ntstatus,
+ &mask_contains_wcard);
+ }
if (!NT_STATUS_IS_OK(ntstatus)) {
reply_nterror(req, ntstatus);
goto out;
if (backup_priv) {
become_root();
as_root = true;
- ntstatus = filename_convert_with_privilege(ctx,
+ ntstatus = filename_convert_with_privilege(talloc_tos(),
conn,
req,
directory,
&mask_contains_wcard,
&smb_dname);
} else {
- ntstatus = filename_convert(ctx, conn,
- req->flags2 & FLAGS2_DFS_PATHNAMES,
+ ntstatus = filename_convert(talloc_tos(), conn,
directory,
ucf_flags,
&mask_contains_wcard,
if(p == NULL) {
/* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
if((directory[0] == '.') && (directory[1] == '\0')) {
- mask = talloc_strdup(ctx,"*");
+ mask = talloc_strdup(talloc_tos(),"*");
if (!mask) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
goto out;
reply_nterror(req, NT_STATUS_NO_MEMORY);
goto out;
}
+ /* Ensure smb_dname->base_name matches. */
+ smb_dname->base_name = directory;
}
DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
}
/* Pull out the list of names. */
- ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
+ ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
if (!ea_list) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
goto out;
ntstatus = dptr_create(conn,
req,
NULL, /* fsp */
- directory,
+ smb_dname,
False,
True,
req->smbpid,
dptr_num = dptr_dnum(dirptr);
DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
- /* Initialize per TRANS2_FIND_FIRST operation data */
- dptr_init_search_op(dirptr);
-
/* We don't need to check for VOL here as this is returned by
a different TRANS2 call. */
DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
- directory,lp_dont_descend(ctx, SNUM(conn))));
- if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
+ directory,lp_dont_descend(talloc_tos(), SNUM(conn))));
+ if (in_list(directory,
+ lp_dont_descend(talloc_tos(), SNUM(conn)),
+ conn->case_sensitive)) {
dont_descend = True;
+ }
p = pdata;
space_remaining = max_data_bytes;
out_of_space = True;
finished = False;
} else {
- ntstatus = get_lanman2_dir_entry(ctx,
+ ntstatus = get_lanman2_dir_entry(talloc_tos(),
conn,
dirptr,
req->flags2,
if (!continue_bit) {
/* We only need resume_name if continue_bit is zero. */
- srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
- params+12,
- total_params - 12, STR_TERMINATE, &ntstatus,
- &mask_contains_wcard);
+ if (req->posix_pathnames) {
+ srvstr_get_path_wcard_posix(ctx,
+ params,
+ req->flags2,
+ &resume_name,
+ params+12,
+ total_params - 12,
+ STR_TERMINATE,
+ &ntstatus,
+ &mask_contains_wcard);
+ } else {
+ srvstr_get_path_wcard(ctx,
+ params,
+ req->flags2,
+ &resume_name,
+ params+12,
+ total_params - 12,
+ STR_TERMINATE,
+ &ntstatus,
+ &mask_contains_wcard);
+ }
if (!NT_STATUS_IS_OK(ntstatus)) {
/* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
complain (it thinks we're asking for the directory above the shared
dptr_TellDir(dirptr),
(int)backup_priv));
- /* Initialize per TRANS2_FIND_NEXT operation data */
- dptr_init_search_op(dirptr);
-
/* We don't need to check for VOL here as this is returned by
a different TRANS2 call. */
ZERO_STRUCT(smb_fname);
smb_fname.base_name = discard_const_p(char, filename);
- if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
+ if(info_level != SMB_FS_QUOTA_INFORMATION
+ && SMB_VFS_STAT(conn, &smb_fname) != 0) {
DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
return map_nt_error_from_unix(errno);
}
{
uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
data_len = 18;
- df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
- &dsize);
+ df_ret = get_dfree_info(conn, &smb_fname, &bsize,
+ &dfree, &dsize);
if (df_ret == (uint64_t)-1) {
return map_nt_error_from_unix(errno);
}
cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
(unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
+ /*
+ * For large drives, return max values and not modulo.
+ */
+ dsize = MIN(dsize, UINT32_MAX);
+ dfree = MIN(dfree, UINT32_MAX);
+
SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
SIVAL(pdata,l1_cUnit,dsize);
{
uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
data_len = 24;
- df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
- &dsize);
+ df_ret = get_dfree_info(conn, &smb_fname, &bsize,
+ &dfree, &dsize);
if (df_ret == (uint64_t)-1) {
return map_nt_error_from_unix(errno);
}
{
uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
data_len = 32;
- df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
- &dsize);
+ df_ret = get_dfree_info(conn, &smb_fname, &bsize,
+ &dfree, &dsize);
if (df_ret == (uint64_t)-1) {
return map_nt_error_from_unix(errno);
}
return NT_STATUS_ACCESS_DENIED;
}
- if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
+ status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
+ NULL, "as);
+ if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
- return map_nt_error_from_unix(errno);
+ return status;
}
data_len = 48;
return NT_STATUS_INVALID_LEVEL;
}
- rc = SMB_VFS_STATVFS(conn, filename, &svfs);
+ rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
if (!rc) {
data_len = 56;
SIVAL(pdata,84,0x100); /* Don't support mac... */
break;
}
- /* drop through */
+
+ FALL_THROUGH;
default:
return NT_STATUS_INVALID_LEVEL;
}
return status;
}
+static NTSTATUS smb_set_fsquota(connection_struct *conn,
+ struct smb_request *req,
+ files_struct *fsp,
+ const DATA_BLOB *qdata)
+{
+ NTSTATUS status;
+ SMB_NTQUOTA_STRUCT quotas;
+
+ ZERO_STRUCT(quotas);
+
+ /* access check */
+ if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
+ DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
+ lp_servicename(talloc_tos(), SNUM(conn)),
+ conn->session_info->unix_info->unix_name));
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ if (!check_fsp_ntquota_handle(conn, req,
+ fsp)) {
+ DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
+ return NT_STATUS_INVALID_HANDLE;
+ }
+
+ /* note: normally there're 48 bytes,
+ * but we didn't use the last 6 bytes for now
+ * --metze
+ */
+ if (qdata->length < 42) {
+ DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
+ (unsigned int)qdata->length));
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /* unknown_1 24 NULL bytes in pdata*/
+
+ /* the soft quotas 8 bytes (uint64_t)*/
+ quotas.softlim = BVAL(qdata->data,24);
+
+ /* the hard quotas 8 bytes (uint64_t)*/
+ quotas.hardlim = BVAL(qdata->data,32);
+
+ /* quota_flags 2 bytes **/
+ quotas.qflags = SVAL(qdata->data,40);
+
+ /* unknown_2 6 NULL bytes follow*/
+
+ /* now set the quotas */
+ if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
+ DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
+ lp_servicename(talloc_tos(), SNUM(conn))));
+ status = map_nt_error_from_unix(errno);
+ } else {
+ status = NT_STATUS_OK;
+ }
+ return status;
+}
+
+NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
+ struct smb_request *req,
+ TALLOC_CTX *mem_ctx,
+ uint16_t info_level,
+ files_struct *fsp,
+ const DATA_BLOB *pdata)
+{
+ switch (info_level) {
+ case SMB_FS_QUOTA_INFORMATION:
+ {
+ return smb_set_fsquota(conn,
+ req,
+ fsp,
+ pdata);
+ }
+
+ default:
+ break;
+ }
+ return NT_STATUS_INVALID_LEVEL;
+}
+
/****************************************************************************
Reply to a TRANS2_QFSINFO (query filesystem info).
****************************************************************************/
case SMB_FS_QUOTA_INFORMATION:
{
+ NTSTATUS status;
+ DATA_BLOB qdata = {
+ .data = (uint8_t *)pdata,
+ .length = total_data
+ };
files_struct *fsp = NULL;
- SMB_NTQUOTA_STRUCT quotas;
-
- ZERO_STRUCT(quotas);
-
- /* access check */
- if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
- DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
- lp_servicename(talloc_tos(), SNUM(conn)),
- conn->session_info->unix_info->unix_name));
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
- return;
- }
-
- /* note: normally there're 48 bytes,
- * but we didn't use the last 6 bytes for now
- * --metze
- */
fsp = file_fsp(req, SVAL(params,0));
- if (!check_fsp_ntquota_handle(conn, req,
- fsp)) {
- DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
- reply_nterror(
- req, NT_STATUS_INVALID_HANDLE);
- return;
- }
-
- if (total_data < 42) {
- DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
- total_data));
- reply_nterror(
- req,
- NT_STATUS_INVALID_PARAMETER);
- return;
- }
-
- /* unknown_1 24 NULL bytes in pdata*/
-
- /* the soft quotas 8 bytes (uint64_t)*/
- quotas.softlim = BVAL(pdata,24);
-
- /* the hard quotas 8 bytes (uint64_t)*/
- quotas.hardlim = BVAL(pdata,32);
-
- /* quota_flags 2 bytes **/
- quotas.qflags = SVAL(pdata,40);
-
- /* unknown_2 6 NULL bytes follow*/
-
- /* now set the quotas */
- if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
- DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
- reply_nterror(req, map_nt_error_from_unix(errno));
+ status = smb_set_fsquota(conn,
+ req,
+ fsp,
+ &qdata);
+ if (!NT_STATUS_IS_OK(status)) {
+ reply_nterror(req, status);
return;
}
-
break;
}
default:
return NT_STATUS_INVALID_PARAMETER;
}
- status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
- talloc_tos(), &num_streams, &streams);
+ status = vfs_streaminfo(conn,
+ fsp,
+ smb_fname,
+ talloc_tos(),
+ &num_streams,
+ &streams);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10, ("could not get stream info: %s\n",
return NT_STATUS_DOS(ERRDOS, ERRbadlink);
#endif
link_len = SMB_VFS_READLINK(conn,
- smb_fname->base_name,
+ smb_fname,
buffer, PATH_MAX);
if (link_len == -1) {
return map_nt_error_from_unix(errno);
uint16_t num_file_acls = 0;
uint16_t num_def_acls = 0;
+ status = refuse_symlink(conn,
+ fsp,
+ smb_fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
if (fsp && fsp->fh->fd != -1) {
file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
talloc_tos());
} else {
file_acl =
SMB_VFS_SYS_ACL_GET_FILE(conn,
- smb_fname->base_name,
+ smb_fname,
SMB_ACL_TYPE_ACCESS,
talloc_tos());
}
def_acl =
SMB_VFS_SYS_ACL_GET_FILE(
conn,
- fsp->fsp_name->base_name,
+ fsp->fsp_name,
SMB_ACL_TYPE_DEFAULT,
talloc_tos());
} else {
def_acl =
SMB_VFS_SYS_ACL_GET_FILE(
conn,
- smb_fname->base_name,
+ smb_fname,
SMB_ACL_TYPE_DEFAULT,
talloc_tos());
}
} else {
uint32_t name_hash;
char *fname = NULL;
- uint32_t ucf_flags = (lp_posix_pathnames() ?
- UCF_POSIX_PATHNAMES : 0);
+ uint32_t ucf_flags = ucf_flags_from_smb_request(req);
/* qpathinfo */
if (total_params < 7) {
}
if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
- info_level == SMB_QUERY_FILE_UNIX_LINK) {
+ info_level == SMB_QUERY_FILE_UNIX_LINK ||
+ req->posix_pathnames) {
ucf_flags |= UCF_UNIX_NAME_LOOKUP;
}
}
- srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
+ if (req->posix_pathnames) {
+ srvstr_get_path_posix(req,
+ params,
+ req->flags2,
+ &fname,
+ ¶ms[6],
total_params - 6,
- STR_TERMINATE, &status);
+ 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;
status = filename_convert(req,
conn,
- req->flags2 & FLAGS2_DFS_PATHNAMES,
fname,
ucf_flags,
NULL,
/* Create an smb_filename with stream_name == NULL. */
smb_fname_base = synthetic_smb_fname(
- talloc_tos(), smb_fname->base_name,
- NULL, NULL);
+ talloc_tos(),
+ smb_fname->base_name,
+ NULL,
+ NULL,
+ smb_fname->flags);
if (smb_fname_base == NULL) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
return;
}
- if (INFO_LEVEL_IS_UNIX(info_level)) {
+ if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
/* Always do lstat for UNIX calls. */
if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
DEBUG(3,("call_trans2qfilepathinfo: "
}
}
- if (INFO_LEVEL_IS_UNIX(info_level)) {
+ if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
/* Always do lstat for UNIX calls. */
if (SMB_VFS_LSTAT(conn, smb_fname)) {
DEBUG(3,("call_trans2qfilepathinfo: "
DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
smb_fname_old->base_name, smb_fname_new->base_name));
- if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
- smb_fname_new->base_name) != 0) {
+ if (SMB_VFS_LINK(conn, smb_fname_old, smb_fname_new) != 0) {
status = map_nt_error_from_unix(errno);
DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
nt_errstr(status), smb_fname_old->base_name,
}
/* Always operate on the base_name, even if a stream was passed in. */
- smb_fname_base = synthetic_smb_fname(
- talloc_tos(), smb_fname->base_name, NULL, &smb_fname->st);
+ smb_fname_base = synthetic_smb_fname(talloc_tos(),
+ smb_fname->base_name,
+ NULL,
+ &smb_fname->st,
+ smb_fname->flags);
if (smb_fname_base == NULL) {
return NT_STATUS_NO_MEMORY;
}
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
- DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
+ DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
+ (uint64_t)size,
+ get_file_size_stat(psbuf));
if (size == get_file_size_stat(psbuf)) {
return NT_STATUS_OK;
struct smb_request *req,
const char *pdata,
int total_data,
- const struct smb_filename *smb_fname)
+ const struct smb_filename *new_smb_fname)
{
char *link_target = NULL;
- const char *newname = smb_fname->base_name;
TALLOC_CTX *ctx = talloc_tos();
/* Set a symbolic link. */
}
DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
- newname, link_target ));
+ new_smb_fname->base_name, link_target ));
- if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
+ if (SMB_VFS_SYMLINK(conn,link_target,new_smb_fname) != 0) {
return map_nt_error_from_unix(errno);
}
{
char *oldname = NULL;
struct smb_filename *smb_fname_old = NULL;
- uint32_t ucf_flags = (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
+ uint32_t ucf_flags = ucf_flags_from_smb_request(req);
TALLOC_CTX *ctx = talloc_tos();
NTSTATUS status = NT_STATUS_OK;
return NT_STATUS_INVALID_PARAMETER;
}
- srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
- total_data, STR_TERMINATE, &status);
+ if (req->posix_pathnames) {
+ srvstr_get_path_posix(ctx,
+ pdata,
+ req->flags2,
+ &oldname,
+ pdata,
+ total_data,
+ STR_TERMINATE,
+ &status);
+ } else {
+ srvstr_get_path(ctx,
+ pdata,
+ req->flags2,
+ &oldname,
+ pdata,
+ total_data,
+ STR_TERMINATE,
+ &status);
+ }
if (!NT_STATUS_IS_OK(status)) {
return status;
}
status = filename_convert(ctx,
conn,
- req->flags2 & FLAGS2_DFS_PATHNAMES,
oldname,
ucf_flags,
NULL,
char *newname = NULL;
struct smb_filename *smb_fname_dst = NULL;
uint32_t ucf_flags = UCF_SAVE_LCOMP |
- (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
+ ucf_flags_from_smb_request(req);
NTSTATUS status = NT_STATUS_OK;
TALLOC_CTX *ctx = talloc_tos();
return NT_STATUS_INVALID_PARAMETER;
}
- srvstr_get_path(ctx, pdata, req->flags2, &newname,
- &pdata[20], len, STR_TERMINATE,
+ if (req->posix_pathnames) {
+ srvstr_get_path_posix(ctx,
+ pdata,
+ req->flags2,
+ &newname,
+ &pdata[20],
+ len,
+ STR_TERMINATE,
+ &status);
+ } else {
+ srvstr_get_path(ctx,
+ pdata,
+ req->flags2,
+ &newname,
+ &pdata[20],
+ len,
+ STR_TERMINATE,
&status);
+ }
if (!NT_STATUS_IS_OK(status)) {
return status;
}
status = filename_convert(ctx,
conn,
- req->flags2 & FLAGS2_DFS_PATHNAMES,
newname,
ucf_flags,
NULL,
}
/* Create an smb_fname to call rename_internals_fsp() with. */
- smb_fname_dst = synthetic_smb_fname(
- talloc_tos(), fsp->base_fsp->fsp_name->base_name,
- newname, NULL);
+ smb_fname_dst = synthetic_smb_fname(talloc_tos(),
+ fsp->base_fsp->fsp_name->base_name,
+ newname,
+ NULL,
+ fsp->base_fsp->fsp_name->flags);
if (smb_fname_dst == NULL) {
status = NT_STATUS_NO_MEMORY;
goto out;
struct smb_filename *smb_fname_dst = NULL;
NTSTATUS status = NT_STATUS_OK;
uint32_t ucf_flags = UCF_SAVE_LCOMP |
- (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
+ ucf_flags_from_smb_request(req);
TALLOC_CTX *ctx = talloc_tos();
if (!fsp) {
return NT_STATUS_INVALID_PARAMETER;
}
- srvstr_get_path(ctx, pdata, req->flags2, &newname,
- &pdata[20], len, STR_TERMINATE,
+ if (req->posix_pathnames) {
+ srvstr_get_path_posix(ctx,
+ pdata,
+ req->flags2,
+ &newname,
+ &pdata[20],
+ len,
+ STR_TERMINATE,
+ &status);
+ } else {
+ srvstr_get_path(ctx,
+ pdata,
+ req->flags2,
+ &newname,
+ &pdata[20],
+ len,
+ STR_TERMINATE,
&status);
+ }
if (!NT_STATUS_IS_OK(status)) {
return status;
}
status = filename_convert(ctx,
conn,
- req->flags2 & FLAGS2_DFS_PATHNAMES,
newname,
ucf_flags,
NULL,
return NT_STATUS_INVALID_PARAMETER;
}
- srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
- len, 0, &status,
- &dest_has_wcard);
+ if (req->posix_pathnames) {
+ srvstr_get_path_wcard_posix(ctx,
+ pdata,
+ req->flags2,
+ &newname,
+ &pdata[12],
+ len,
+ 0,
+ &status,
+ &dest_has_wcard);
+ } else {
+ srvstr_get_path_wcard(ctx,
+ pdata,
+ req->flags2,
+ &newname,
+ &pdata[12],
+ len,
+ 0,
+ &status,
+ &dest_has_wcard);
+ }
if (!NT_STATUS_IS_OK(status)) {
return status;
}
DEBUG(10,("smb_file_rename_information: got name |%s|\n",
newname));
- status = resolve_dfspath_wcard(ctx, conn,
- req->flags2 & FLAGS2_DFS_PATHNAMES,
+ if (req->flags2 & FLAGS2_DFS_PATHNAMES) {
+ status = resolve_dfspath_wcard(ctx, conn,
newname,
- true,
+ UCF_COND_ALLOW_WCARD_LCOMP,
!conn->sconn->using_smb2,
&newname,
&dest_has_wcard);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
}
/* Check the new name has no '/' characters. */
}
/* Create an smb_fname to call rename_internals_fsp() with. */
- smb_fname_dst = synthetic_smb_fname(
- talloc_tos(), fsp->base_fsp->fsp_name->base_name,
- newname, NULL);
+ smb_fname_dst = synthetic_smb_fname(talloc_tos(),
+ fsp->base_fsp->fsp_name->base_name,
+ newname,
+ NULL,
+ fsp->base_fsp->fsp_name->flags);
if (smb_fname_dst == NULL) {
status = NT_STATUS_NO_MEMORY;
goto out;
* the newname instead.
*/
char *base_name = NULL;
+ uint32_t ucf_flags = UCF_SAVE_LCOMP |
+ ucf_flags_from_smb_request(req);
+
+ if (dest_has_wcard) {
+ ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
+ }
/* newname must *not* be a stream name. */
if (newname[0] == ':') {
}
status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
- (UCF_SAVE_LCOMP |
- (dest_has_wcard ?
- UCF_ALWAYS_ALLOW_WCARD_LCOMP :
- 0)));
+ ucf_flags);
/* If an error we expect this to be
* NT_STATUS_OBJECT_PATH_NOT_FOUND */
goto out;
}
/* Create an smb_fname to call rename_internals_fsp() */
- smb_fname_dst = synthetic_smb_fname(
- ctx, base_name, NULL, NULL);
+ smb_fname_dst = synthetic_smb_fname(ctx,
+ base_name,
+ NULL,
+ NULL,
+ smb_fname_src->flags);
if (smb_fname_dst == NULL) {
status = NT_STATUS_NO_MEMORY;
goto out;
uint16_t num_def_acls;
bool valid_file_acls = True;
bool valid_def_acls = True;
+ NTSTATUS status;
if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
return NT_STATUS_INVALID_PARAMETER;
return NT_STATUS_INVALID_PARAMETER;
}
+ status = refuse_symlink(conn, fsp, smb_fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
(unsigned int)num_file_acls,
(unsigned int)num_def_acls));
if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
- smb_fname->base_name, num_file_acls,
+ smb_fname, num_file_acls,
pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
return map_nt_error_from_unix(errno);
}
if (valid_def_acls && !set_unix_posix_default_acl(conn,
- smb_fname->base_name, &smb_fname->st, num_def_acls,
+ smb_fname, num_def_acls,
pdata + SMB_POSIX_ACL_HEADER_SIZE +
(num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
return map_nt_error_from_unix(errno);
(unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
/* Ok - do the mknod. */
- if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
+ if (SMB_VFS_MKNOD(conn, smb_fname, unixmode, dev) != 0) {
return map_nt_error_from_unix(errno);
}
&parent, NULL)) {
return NT_STATUS_NO_MEMORY;
}
- inherit_access_posix_acl(conn, parent, smb_fname->base_name,
+ inherit_access_posix_acl(conn, parent, smb_fname,
unixmode);
TALLOC_FREE(parent);
}
if (fsp && fsp->fh->fd != -1) {
ret = SMB_VFS_FCHMOD(fsp, unixmode);
} else {
- ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode);
+ ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
}
if (ret != 0) {
return map_nt_error_from_unix(errno);
* UNIX extensions calls must always operate
* on symlinks.
*/
- ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
+ ret = SMB_VFS_LCHOWN(conn, smb_fname,
set_owner, (gid_t)-1);
}
DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
"changing group %u for file %s\n",
- (unsigned int)set_owner,
+ (unsigned int)set_grp,
smb_fname_str_dbg(smb_fname)));
if (fsp && fsp->fh->fd != -1) {
- ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
+ ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
} else {
/*
* UNIX extensions calls must always operate
* on symlinks.
*/
- ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, (uid_t)-1,
+ ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
set_grp);
}
if (ret != 0) {
/* XXX: we should be using SMB_VFS_FCHFLAGS here. */
return NT_STATUS_NOT_SUPPORTED;
} else {
- if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
+ if (SMB_VFS_CHFLAGS(conn, smb_fname,
stat_fflags) != 0) {
return map_nt_error_from_unix(errno);
}
int total_data,
struct smb_filename *smb_fname)
{
+ struct server_id self = messaging_server_id(conn->sconn->msg_ctx);
NTSTATUS status = NT_STATUS_OK;
files_struct *fsp = NULL;
uint16_t flags = 0;
char del = 1;
int info = 0;
int create_options = 0;
- int i;
struct share_mode_lock *lck = NULL;
+ bool other_nonposix_opens;
if (total_data < 2) {
return NT_STATUS_INVALID_PARAMETER;
return NT_STATUS_INVALID_PARAMETER;
}
- /*
- * See if others still have the file open. If this is the case, then
- * don't delete. If all opens are POSIX delete we can set the delete
- * on close disposition.
- */
- for (i=0; i<lck->data->num_share_modes; i++) {
- struct share_mode_entry *e = &lck->data->share_modes[i];
- if (is_valid_share_mode_entry(e)) {
- if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
- continue;
- }
- if (share_mode_stale_pid(lck->data, i)) {
- continue;
- }
- /* Fail with sharing violation. */
- TALLOC_FREE(lck);
- close_file(req, fsp, NORMAL_CLOSE);
- return NT_STATUS_SHARING_VIOLATION;
- }
+ other_nonposix_opens = has_other_nonposix_opens(lck, fsp, self);
+ if (other_nonposix_opens) {
+ /* Fail with sharing violation. */
+ TALLOC_FREE(lck);
+ close_file(req, fsp, NORMAL_CLOSE);
+ return NT_STATUS_SHARING_VIOLATION;
}
/*
break;
}
+ /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
+ case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
+ case SMB_FILE_SHORT_NAME_INFORMATION:
+ return NT_STATUS_NOT_SUPPORTED;
+
/*
* CIFS UNIX extensions.
*/
}
} else {
char *fname = NULL;
- uint32_t ucf_flags = (lp_posix_pathnames() ?
- UCF_POSIX_PATHNAMES : 0);
+ uint32_t ucf_flags = ucf_flags_from_smb_request(req);
/* set path info */
if (total_params < 7) {
}
info_level = SVAL(params,0);
- srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
- total_params - 6, STR_TERMINATE,
+ 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;
}
status = filename_convert(req, conn,
- req->flags2 & FLAGS2_DFS_PATHNAMES,
fname,
ucf_flags,
NULL,
char *directory = NULL;
NTSTATUS status = NT_STATUS_OK;
struct ea_list *ea_list = NULL;
- uint32_t ucf_flags = (lp_posix_pathnames() ? UCF_POSIX_PATHNAMES : 0);
+ uint32_t ucf_flags = ucf_flags_from_smb_request(req);
TALLOC_CTX *ctx = talloc_tos();
if (!CAN_WRITE(conn)) {
return;
}
- srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
- total_params - 4, STR_TERMINATE,
+ if (req->posix_pathnames) {
+ srvstr_get_path_posix(ctx,
+ params,
+ req->flags2,
+ &directory,
+ ¶ms[4],
+ total_params - 4,
+ STR_TERMINATE,
&status);
+ } else {
+ srvstr_get_path(ctx,
+ params,
+ req->flags2,
+ &directory,
+ ¶ms[4],
+ total_params - 4,
+ STR_TERMINATE,
+ &status);
+ }
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
return;
status = filename_convert(ctx,
conn,
- req->flags2 & FLAGS2_DFS_PATHNAMES,
directory,
ucf_flags,
NULL,