#include "rpc_server/srv_pipe_hnd.h"
#include "printing.h"
#include "lib/util_ea.h"
+#include "lib/readdir_attr.h"
#define DIR_ENTRY_SAFETY_MARGIN 4096
files_struct *fsp,
const SMB_STRUCT_STAT *psbuf);
+/****************************************************************************
+ Check if an open file handle or pathname is a symlink.
+****************************************************************************/
+
+static NTSTATUS refuse_symlink(connection_struct *conn,
+ const files_struct *fsp,
+ const char *name)
+{
+ SMB_STRUCT_STAT sbuf;
+ const SMB_STRUCT_STAT *pst = NULL;
+
+ if (fsp) {
+ pst = &fsp->fsp_name->st;
+ } else {
+ int ret = vfs_stat_smb_basename(conn,
+ name,
+ &sbuf);
+ if (ret == -1) {
+ return map_nt_error_from_unix(errno);
+ }
+ 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)
+{
+ if (!(fsp->access_mask & access_mask)) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ return NT_STATUS_OK;
+}
+
/********************************************************************
The canonical "check access" based on object handle or path function.
********************************************************************/
const struct smb_filename *smb_fname,
uint32_t access_mask)
{
+ NTSTATUS status;
+
if (fsp) {
- if (!(fsp->access_mask & access_mask)) {
- return NT_STATUS_ACCESS_DENIED;
- }
+ status = check_access_fsp(fsp, access_mask);
} else {
- NTSTATUS status = smbd_check_access_rights(conn,
- smb_fname,
- false,
- access_mask);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
+ status = smbd_check_access_rights(conn, smb_fname,
+ false, access_mask);
}
- return NT_STATUS_OK;
+
+ return status;
}
/********************************************************************
}
DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
- dump_data(10, (uint8 *)val, sizeret);
+ dump_data(10, (uint8_t *)val, sizeret);
pea->flags = 0;
if (strnequal(ea_name, "user.", 5)) {
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)
{
/* Get a list of all xattrs. Max namesize is 64k. */
size_t ea_namelist_size = 1024;
char **names, **tmp;
size_t num_names;
ssize_t sizeret = -1;
+ NTSTATUS status;
+
+ if (pnames) {
+ *pnames = NULL;
+ }
+ *pnum_names = 0;
if (!lp_ea_support(SNUM(conn))) {
- if (pnames) {
- *pnames = NULL;
- }
- *pnum_names = 0;
+ return NT_STATUS_OK;
+ }
+
+ status = refuse_symlink(conn, fsp, smb_fname->base_name);
+ if (!NT_STATUS_IS_OK(status)) {
+ /*
+ * Just return no EA's on a symlink.
+ */
return NT_STATUS_OK;
}
sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
ea_namelist_size);
} else {
- sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
- ea_namelist_size);
+ sizeret = SMB_VFS_LISTXATTR(conn,
+ smb_fname->base_name,
+ ea_namelist,
+ ea_namelist_size);
}
if ((sizeret == -1) && (errno == ERANGE)) {
if (sizeret == 0) {
TALLOC_FREE(names);
- if (pnames) {
- *pnames = NULL;
- }
- *pnum_names = 0;
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;
*pea_total_len = 0;
*ea_list = NULL;
- status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
- &names, &num_names);
+ status = get_ea_names_from_file(talloc_tos(),
+ conn,
+ fsp,
+ smb_fname,
+ &names,
+ &num_names);
if (!NT_STATUS_IS_OK(status)) {
return status;
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->base_name,
+ 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;
if (!lp_ea_support(SNUM(conn))) {
return NT_STATUS_EAS_NOT_SUPPORTED;
}
+ status = refuse_symlink(conn, fsp, smb_fname->base_name);
+ 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;
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->base_name,
+ 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->base_name,
+ 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;
}
int data_alignment_offset = 0;
bool overflow = False;
struct smbXsrv_connection *xconn = req->xconn;
- struct smbd_server_connection *sconn = xconn->sconn;
int max_send = xconn->smb1.sessions.max_send;
/* Modify the data_to_send and datasize and set the error if
__LINE__,__FILE__);
}
show_msg((char *)req->outbuf);
- if (!srv_send_smb(sconn,
+ if (!srv_send_smb(xconn,
(char *)req->outbuf,
true, req->seqnum+1,
IS_CONN_ENCRYPTED(conn),
/* Send the packet */
show_msg((char *)req->outbuf);
- if (!srv_send_smb(sconn,
+ if (!srv_send_smb(xconn,
(char *)req->outbuf,
true, req->seqnum+1,
IS_CONN_ENCRYPTED(conn),
char *params = *pparams;
char *pdata = *ppdata;
int deny_mode;
- int32 open_attr;
+ int32_t open_attr;
bool oplock_request;
#if 0
bool return_additional_info;
time_t open_time;
#endif
int open_ofun;
- uint32 open_size;
+ uint32_t open_size;
char *pname;
char *fname = NULL;
off_t size=0;
int smb_action = 0;
files_struct *fsp;
struct ea_list *ea_list = NULL;
- uint16 flags = 0;
+ uint16_t flags = 0;
NTSTATUS status;
- uint32 access_mask;
- uint32 share_mode;
- uint32 create_disposition;
- uint32 create_options = 0;
+ uint32_t access_mask;
+ uint32_t share_mode;
+ uint32_t create_disposition;
+ uint32_t create_options = 0;
uint32_t private_flags = 0;
+ uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
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;
conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
fname,
- 0,
+ ucf_flags,
NULL,
&smb_fname);
if (!NT_STATUS_IS_OK(status)) {
NULL, /* sd */
ea_list, /* ea_list */
&fsp, /* result */
- &smb_action); /* psbuf */
+ &smb_action, /* psbuf */
+ NULL, NULL); /* create context */
if (!NT_STATUS_IS_OK(status)) {
- if (open_was_deferred(req->sconn, req->mid)) {
+ if (open_was_deferred(req->xconn, req->mid)) {
/* We have re-scheduled this call. */
goto out;
}
SSVAL(params,0,fsp->fnum);
SSVAL(params,2,fattr);
srv_put_dos_date2(params,4, mtime);
- SIVAL(params,8, (uint32)size);
+ SIVAL(params,8, (uint32_t)size);
SSVAL(params,12,deny_mode);
SSVAL(params,14,0); /* open_type - file or directory. */
SSVAL(params,16,0); /* open_state - only valid for IPC device. */
SIVAL(params,20,inode);
SSVAL(params,24,0); /* Padding. */
if (flags & 8) {
- uint32 ea_size = estimate_ea_size(conn, fsp,
+ uint32_t ea_size = estimate_ea_size(conn, fsp,
smb_fname);
SIVAL(params, 26, ea_size);
} else {
Return the filetype for UNIX extensions.
****************************************************************************/
-static uint32 unix_filetype(mode_t mode)
+static uint32_t unix_filetype(mode_t mode)
{
if(S_ISREG(mode))
return UNIX_TYPE_FILE;
static NTSTATUS unix_perms_from_wire( connection_struct *conn,
const SMB_STRUCT_STAT *psbuf,
- uint32 perms,
+ uint32_t perms,
enum perm_type ptype,
mode_t *ret_perms)
{
/* Mangle fname if it's an illegal name. */
if (mangle_must_mangle(dname, state->conn->params)) {
+ /*
+ * Slow path - ensure we can push the original name as UCS2. If
+ * not, then just don't return this name.
+ */
+ NTSTATUS status;
+ size_t ret_len = 0;
+ size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
+ uint8_t *tmp = talloc_array(talloc_tos(),
+ uint8_t,
+ len);
+
+ status = srvstr_push(NULL,
+ FLAGS2_UNICODE_STRINGS,
+ tmp,
+ dname,
+ len,
+ STR_TERMINATE,
+ &ret_len);
+
+ TALLOC_FREE(tmp);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return false;
+ }
+
ok = name_to_8_3(dname, mangled_name,
true, state->conn->params);
if (!ok) {
return true;
}
-static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
+static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
connection_struct *conn,
uint16_t flags2,
uint32_t info_level,
char *base_data,
char **ppdata,
char *end_data,
- bool *out_of_space,
uint64_t *last_entry_off)
{
char *p, *q, *pdata = *ppdata;
uint64_t allocation_size = 0;
uint64_t file_index = 0;
size_t len = 0;
- struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
+ struct timespec mdate_ts = {0};
+ struct timespec adate_ts = {0};
+ struct timespec cdate_ts = {0};
+ struct timespec create_date_ts = {0};
time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
char *nameptr;
char *last_entry_ptr;
int off;
int pad = 0;
NTSTATUS status;
-
- *out_of_space = false;
-
- ZERO_STRUCT(mdate_ts);
- ZERO_STRUCT(adate_ts);
- ZERO_STRUCT(create_date_ts);
- ZERO_STRUCT(cdate_ts);
+ struct readdir_attr_data *readdir_attr_data = NULL;
if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
file_size = get_file_size_stat(&smb_fname->st);
}
allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
+ status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
+ if (!NT_STATUS_IS_OK(status)) {
+ if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
+ return status;
+ }
+ }
+
file_index = get_FileIndex(conn, &smb_fname->st);
mdate_ts = smb_fname->st.st_ex_mtime;
pad -= off;
if (pad && pad > space_remaining) {
- *out_of_space = true;
DEBUG(9,("smbd_marshall_dir_entry: out of space "
"for padding (wanted %u, had %d)\n",
(unsigned int)pad,
space_remaining ));
- return false; /* Not finished - just out of space */
+ return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
}
off += pad;
srv_put_dos_date2(p,0,create_date);
srv_put_dos_date2(p,4,adate);
srv_put_dos_date2(p,8,mdate);
- SIVAL(p,12,(uint32)file_size);
- SIVAL(p,16,(uint32)allocation_size);
+ SIVAL(p,12,(uint32_t)file_size);
+ SIVAL(p,16,(uint32_t)allocation_size);
SSVAL(p,20,mode);
p += 23;
nameptr = p;
fname, PTR_DIFF(end_data, p),
STR_TERMINATE, &len);
if (!NT_STATUS_IS_OK(status)) {
- return false;
+ return status;
}
if (flags2 & FLAGS2_UNICODE_STRINGS) {
if (len > 2) {
srv_put_dos_date2(p,0,create_date);
srv_put_dos_date2(p,4,adate);
srv_put_dos_date2(p,8,mdate);
- SIVAL(p,12,(uint32)file_size);
- SIVAL(p,16,(uint32)allocation_size);
+ SIVAL(p,12,(uint32_t)file_size);
+ SIVAL(p,16,(uint32_t)allocation_size);
SSVAL(p,20,mode);
{
unsigned int ea_size = estimate_ea_size(conn, NULL,
p, fname, PTR_DIFF(end_data, p),
STR_TERMINATE | STR_NOALIGN, &len);
if (!NT_STATUS_IS_OK(status)) {
- return false;
+ return status;
}
if (flags2 & FLAGS2_UNICODE_STRINGS) {
if (len > 2) {
DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
if (!name_list) {
- return false;
+ return NT_STATUS_INVALID_PARAMETER;
}
if (requires_resume_key) {
SIVAL(p,0,reskey);
srv_put_dos_date2(p,0,create_date);
srv_put_dos_date2(p,4,adate);
srv_put_dos_date2(p,8,mdate);
- SIVAL(p,12,(uint32)file_size);
- SIVAL(p,16,(uint32)allocation_size);
+ SIVAL(p,12,(uint32_t)file_size);
+ SIVAL(p,16,(uint32_t)allocation_size);
SSVAL(p,20,mode);
p += 22; /* p now points to the EA area. */
/* We need to determine if this entry will fit in the space available. */
/* Max string size is 255 bytes. */
if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
- *out_of_space = true;
DEBUG(9,("smbd_marshall_dir_entry: out of space "
"(wanted %u, had %d)\n",
(unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
space_remaining ));
- return False; /* Not finished - just out of space */
+ return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
}
/* Push the ea_data followed by the name. */
p + 1, fname, PTR_DIFF(end_data, p+1),
STR_TERMINATE | STR_NOALIGN, &len);
if (!NT_STATUS_IS_OK(status)) {
- return false;
+ return status;
}
if (flags2 & FLAGS2_UNICODE_STRINGS) {
if (len > 2) {
p+2, mangled_name, 24,
STR_UPPER|STR_UNICODE, &len);
if (!NT_STATUS_IS_OK(status)) {
- return false;
+ return status;
}
if (len < 24) {
memset(p + 2 + len,'\0',24 - len);
fname, PTR_DIFF(end_data, p),
STR_TERMINATE_ASCII, &len);
if (!NT_STATUS_IS_OK(status)) {
- return false;
+ return status;
}
SIVAL(q,0,len);
p += len;
p + 4, fname, PTR_DIFF(end_data, p+4),
STR_TERMINATE_ASCII, &len);
if (!NT_STATUS_IS_OK(status)) {
- return false;
+ return status;
}
SIVAL(p,0,len);
p += 4 + len;
fname, PTR_DIFF(end_data, p),
STR_TERMINATE_ASCII, &len);
if (!NT_STATUS_IS_OK(status)) {
- return false;
+ return status;
}
SIVAL(q, 0, len);
p += len;
fname, PTR_DIFF(end_data, p),
STR_TERMINATE_ASCII, &len);
if (!NT_STATUS_IS_OK(status)) {
- return false;
+ return status;
}
SIVAL(p, -4, len);
p += len;
fname, PTR_DIFF(end_data, p),
STR_TERMINATE_ASCII, &len);
if (!NT_STATUS_IS_OK(status)) {
- return false;
+ return status;
}
SIVAL(q, 0, len);
p += len;
q = p; p += 4; /* q is placeholder for name length */
if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
SIVAL(p, 0, IO_REPARSE_TAG_DFS);
+ } else if (readdir_attr_data &&
+ readdir_attr_data->type == RDATTR_AAPL) {
+ /*
+ * OS X specific SMB2 extension negotiated via
+ * AAPL create context: return max_access in
+ * ea_size field.
+ */
+ SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
} else {
unsigned int ea_size = estimate_ea_size(conn, NULL,
smb_fname);
SIVAL(p,0,ea_size); /* Extended attributes */
}
p += 4;
- /* Clear the short name buffer. This is
- * IMPORTANT as not doing so will trigger
- * a Win2k client bug. JRA.
- */
- if (!was_8_3 && check_mangled_names) {
+
+ if (readdir_attr_data &&
+ readdir_attr_data->type == RDATTR_AAPL) {
+ /*
+ * OS X specific SMB2 extension negotiated via
+ * AAPL create context: return resource fork
+ * length and compressed FinderInfo in
+ * shortname field.
+ *
+ * According to documentation short_name_len
+ * should be 0, but on the wire behaviour
+ * shows its set to 24 by clients.
+ */
+ SSVAL(p, 0, 24);
+
+ /* Resourefork length */
+ SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
+
+ /* Compressed FinderInfo */
+ memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
+ } else if (!was_8_3 && check_mangled_names) {
char mangled_name[13]; /* mangled 8.3 name. */
if (!name_to_8_3(fname,mangled_name,True,
conn->params)) {
p+2, mangled_name, 24,
STR_UPPER|STR_UNICODE, &len);
if (!NT_STATUS_IS_OK(status)) {
- return false;
+ return status;
}
SSVAL(p, 0, len);
if (len < 24) {
}
SSVAL(p, 0, len);
} else {
+ /* Clear the short name buffer. This is
+ * IMPORTANT as not doing so will trigger
+ * a Win2k client bug. JRA.
+ */
memset(p,'\0',26);
}
p += 26;
- SSVAL(p,0,0); p += 2; /* Reserved ? */
+
+ /* Reserved ? */
+ if (readdir_attr_data &&
+ readdir_attr_data->type == RDATTR_AAPL) {
+ /*
+ * OS X specific SMB2 extension negotiated via
+ * AAPL create context: return UNIX mode in
+ * reserved field.
+ */
+ uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
+ SSVAL(p, 0, aapl_mode);
+ } else {
+ SSVAL(p, 0, 0);
+ }
+ p += 2;
+
SBVAL(p,0,file_index); p += 8;
status = srvstr_push(base_data, flags2, p,
fname, PTR_DIFF(end_data, p),
STR_TERMINATE_ASCII, &len);
if (!NT_STATUS_IS_OK(status)) {
- return false;
+ return status;
}
SIVAL(q,0,len);
p += len;
fname, PTR_DIFF(end_data, p),
STR_TERMINATE, &len);
if (!NT_STATUS_IS_OK(status)) {
- return false;
+ return status;
}
} else {
DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
status = srvstr_push(base_data, flags2, p, fname,
PTR_DIFF(end_data, p), 0, &len);
if (!NT_STATUS_IS_OK(status)) {
- return false;
+ return status;
}
SIVAL(nameptr, 0, len);
}
break;
default:
- return false;
+ return NT_STATUS_INVALID_LEVEL;
}
if (PTR_DIFF(p,pdata) > space_remaining) {
- *out_of_space = true;
DEBUG(9,("smbd_marshall_dir_entry: out of space "
"(wanted %u, had %d)\n",
(unsigned int)PTR_DIFF(p,pdata),
space_remaining ));
- return false; /* Not finished - just out of space */
+ return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
}
/* Setup the last entry pointer, as an offset from base_data */
/* Advance the data pointer to the next slot */
*ppdata = p;
- return true;
+ return NT_STATUS_OK;
}
-bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
+NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
connection_struct *conn,
struct dptr_struct *dirptr,
- uint16 flags2,
+ uint16_t flags2,
const char *path_mask,
- uint32 dirtype,
+ uint32_t dirtype,
int info_level,
int requires_resume_key,
bool dont_descend,
char *base_data,
char *end_data,
int space_remaining,
- bool *out_of_space,
bool *got_exact_match,
int *_last_entry_off,
struct ea_list *name_list)
struct smbd_dirptr_lanman2_state state;
bool ok;
uint64_t last_entry_off = 0;
+ NTSTATUS status;
ZERO_STRUCT(state);
state.conn = conn;
state.has_wild = dptr_has_wild(dirptr);
state.got_exact_match = false;
- *out_of_space = false;
*got_exact_match = false;
p = strrchr_m(path_mask,'/');
&mode,
&prev_dirpos);
if (!ok) {
- return false;
+ return NT_STATUS_END_OF_FILE;
}
*got_exact_match = state.got_exact_match;
- ok = smbd_marshall_dir_entry(ctx,
+ status = smbd_marshall_dir_entry(ctx,
conn,
flags2,
info_level,
base_data,
ppdata,
end_data,
- out_of_space,
&last_entry_off);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
+ DEBUG(1,("Conversion error: illegal character: %s\n",
+ smb_fname_str_dbg(smb_fname)));
+ }
TALLOC_FREE(fname);
TALLOC_FREE(smb_fname);
- if (*out_of_space) {
+ if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
dptr_SeekDir(dirptr, prev_dirpos);
- return false;
+ return status;
}
- if (!ok) {
- return false;
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
*_last_entry_off = last_entry_off;
- return true;
+ return NT_STATUS_OK;
}
-static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
+static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
connection_struct *conn,
struct dptr_struct *dirptr,
- uint16 flags2,
+ uint16_t flags2,
const char *path_mask,
- uint32 dirtype,
+ uint32_t dirtype,
int info_level,
bool requires_resume_key,
bool dont_descend,
char *base_data,
char *end_data,
int space_remaining,
- bool *out_of_space,
bool *got_exact_match,
int *last_entry_off,
struct ea_list *name_list)
align, do_pad,
ppdata, base_data, end_data,
space_remaining,
- out_of_space, got_exact_match,
+ got_exact_match,
last_entry_off, name_list);
}
char *params = *pparams;
char *pdata = *ppdata;
char *data_end;
- uint32 dirtype;
+ uint32_t dirtype;
int maxentries;
- uint16 findfirst_flags;
+ uint16_t findfirst_flags;
bool close_after_first;
bool close_if_end;
bool requires_resume_key;
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);
+ uint32_t ucf_flags = UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP |
+ (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
bool backup_priv = false;
+ bool as_root = false;
if (total_params < 13) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
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();
- ntstatus = filename_convert_with_privilege(ctx,
+ as_root = true;
+ ntstatus = filename_convert_with_privilege(talloc_tos(),
conn,
req,
directory,
&mask_contains_wcard,
&smb_dname);
} else {
- ntstatus = filename_convert(ctx, conn,
+ ntstatus = filename_convert(talloc_tos(), conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
directory,
ucf_flags,
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));
if (info_level == SMB_FIND_EA_LIST) {
- uint32 ea_size;
+ uint32_t ea_size;
if (total_data < 4) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
}
/* 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;
}
pdata = *ppdata;
data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
-
+ /*
+ * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
+ * error.
+ */
+ memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
/* Realloc the params space */
*pparams = (char *)SMB_REALLOC(*pparams, 10);
if (*pparams == NULL) {
ntstatus = dptr_create(conn,
req,
NULL, /* fsp */
- directory,
+ smb_dname,
False,
True,
req->smbpid,
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 {
- finished = !get_lanman2_dir_entry(ctx,
+ ntstatus = get_lanman2_dir_entry(talloc_tos(),
conn,
dirptr,
req->flags2,
requires_resume_key,dont_descend,
ask_sharemode,
&p,pdata,data_end,
- space_remaining, &out_of_space,
+ space_remaining,
&got_exact_match,
&last_entry_off, ea_list);
+ if (NT_STATUS_EQUAL(ntstatus,
+ NT_STATUS_ILLEGAL_CHARACTER)) {
+ /*
+ * Bad character conversion on name. Ignore this
+ * entry.
+ */
+ continue;
+ }
+ if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
+ out_of_space = true;
+ } else {
+ finished = !NT_STATUS_IS_OK(ntstatus);
+ }
}
- if (finished && out_of_space)
- finished = False;
-
if (!finished && !out_of_space)
numentries++;
}
out:
- if (backup_priv) {
+ if (as_root) {
unbecome_root();
}
char *data_end;
int dptr_num;
int maxentries;
- uint16 info_level;
- uint32 resume_key;
- uint16 findnext_flags;
+ uint16_t info_level;
+ uint32_t resume_key;
+ uint16_t findnext_flags;
bool close_after_request;
bool close_if_end;
bool requires_resume_key;
const char *mask = NULL;
const char *directory = NULL;
char *p = NULL;
- uint16 dirtype;
+ uint16_t dirtype;
int numentries = 0;
int i, last_entry_off=0;
bool finished = False;
struct dptr_struct *dirptr;
struct smbd_server_connection *sconn = req->sconn;
bool backup_priv = false;
+ bool as_root = false;
if (total_params < 13) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
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
}
if (info_level == SMB_FIND_EA_LIST) {
- uint32 ea_size;
+ uint32_t ea_size;
if (total_data < 4) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
pdata = *ppdata;
data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
+ /*
+ * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
+ * error.
+ */
+ memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
/* Realloc the params space */
*pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
if(*pparams == NULL ) {
if (backup_priv) {
become_root();
+ as_root = true;
}
/*
out_of_space = True;
finished = False;
} else {
- finished = !get_lanman2_dir_entry(ctx,
+ ntstatus = get_lanman2_dir_entry(ctx,
conn,
dirptr,
req->flags2,
requires_resume_key,dont_descend,
ask_sharemode,
&p,pdata,data_end,
- space_remaining, &out_of_space,
+ space_remaining,
&got_exact_match,
&last_entry_off, ea_list);
+ if (NT_STATUS_EQUAL(ntstatus,
+ NT_STATUS_ILLEGAL_CHARACTER)) {
+ /*
+ * Bad character conversion on name. Ignore this
+ * entry.
+ */
+ continue;
+ }
+ if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
+ out_of_space = true;
+ } else {
+ finished = !NT_STATUS_IS_OK(ntstatus);
+ }
}
- if (finished && out_of_space)
- finished = False;
-
if (!finished && !out_of_space)
numentries++;
dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
}
- if (backup_priv) {
+ if (as_root) {
unbecome_root();
}
int snum = SNUM(conn);
const char *fstype = lp_fstype(SNUM(conn));
const char *filename = NULL;
- uint32 additional_flags = 0;
+ const uint64_t bytes_per_sector = 512;
+ uint32_t additional_flags = 0;
struct smb_filename smb_fname;
SMB_STRUCT_STAT st;
NTSTATUS status = NT_STATUS_OK;
+ uint64_t df_ret;
if (fname == NULL || fname->base_name == NULL) {
filename = ".";
switch (info_level) {
case SMB_INFO_ALLOCATION:
{
- uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
+ uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
data_len = 18;
- if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
+ df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
+ &dsize);
+ if (df_ret == (uint64_t)-1) {
return map_nt_error_from_unix(errno);
}
dsize *= factor;
dfree *= factor;
}
- bytes_per_sector = 512;
sectors_per_unit = bsize/bytes_per_sector;
DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
case SMB_QUERY_FS_SIZE_INFO:
case SMB_FS_SIZE_INFORMATION:
{
- uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
+ uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
data_len = 24;
- if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
+ df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
+ &dsize);
+ if (df_ret == (uint64_t)-1) {
return map_nt_error_from_unix(errno);
}
block_size = lp_block_size(snum);
dsize *= factor;
dfree *= factor;
}
- bytes_per_sector = 512;
sectors_per_unit = bsize/bytes_per_sector;
DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
case SMB_FS_FULL_SIZE_INFORMATION:
{
- uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
+ uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
data_len = 32;
- if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
+ df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
+ &dsize);
+ if (df_ret == (uint64_t)-1) {
return map_nt_error_from_unix(errno);
}
block_size = lp_block_size(snum);
dsize *= factor;
dfree *= factor;
}
- bytes_per_sector = 512;
sectors_per_unit = bsize/bytes_per_sector;
DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
break;
}
+ case SMB_FS_SECTOR_SIZE_INFORMATION:
+ {
+ data_len = 28;
+ /*
+ * These values match a physical Windows Server 2012
+ * share backed by NTFS atop spinning rust.
+ */
+ DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
+ /* logical_bytes_per_sector */
+ SIVAL(pdata, 0, bytes_per_sector);
+ /* phys_bytes_per_sector_atomic */
+ SIVAL(pdata, 4, bytes_per_sector);
+ /* phys_bytes_per_sector_perf */
+ SIVAL(pdata, 8, bytes_per_sector);
+ /* fs_effective_phys_bytes_per_sector_atomic */
+ SIVAL(pdata, 12, bytes_per_sector);
+ /* flags */
+ SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
+ | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
+ /* byte_off_sector_align */
+ SIVAL(pdata, 20, 0);
+ /* byte_off_partition_align */
+ SIVAL(pdata, 24, 0);
+ *fixed_portion = 28;
+ break;
+ }
+
+
/*
* Query the version and capabilities of the CIFS UNIX extensions
* in use.
case SMB_SIGNING_OFF:
encrypt_caps = 0;
break;
+ case SMB_SIGNING_DESIRED:
case SMB_SIGNING_IF_REQUIRED:
case SMB_SIGNING_DEFAULT:
encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
&conn->session_info->security_token->sids[i],
0);
- sid_linearize(pdata + data_len, sid_len,
+ sid_linearize((uint8_t *)(pdata + data_len),
+ sid_len,
&conn->session_info->security_token->sids[i]);
data_len += sid_len;
}
struct smbXsrv_connection *xconn = req->xconn;
char *pdata = *ppdata;
char *params = *pparams;
- uint16 info_level;
+ uint16_t info_level;
DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
lp_servicename(talloc_tos(), SNUM(conn))));
return;
}
- /* note: normaly there're 48 bytes,
+ /* note: normally there're 48 bytes,
* but we didn't use the last 6 bytes for now
* --metze
*/
};
static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
- uint32 *smb_fflags, uint32 *smb_fmask)
+ uint32_t *smb_fflags, uint32_t *smb_fmask)
{
int i;
}
static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
- const uint32 smb_fflags,
- const uint32 smb_fmask,
+ const uint32_t smb_fflags,
+ const uint32_t smb_fmask,
int *stat_fflags)
{
- uint32 max_fmask = 0;
+ uint32_t max_fmask = 0;
int i;
*stat_fflags = psbuf->st_ex_flags;
files_struct *fsp,
const SMB_STRUCT_STAT *psbuf)
{
- uint32 file_flags = 0;
- uint32 flags_mask = 0;
+ uint32_t file_flags = 0;
+ uint32_t flags_mask = 0;
pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
char *pdata = *ppdata;
unsigned int data_size = 0;
unsigned int param_size = 2;
- uint16 info_level;
+ uint16_t info_level;
files_struct *fsp;
if (!params) {
srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
- SIVAL(pdata,l1_cbFile,(uint32)file_size);
- SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
+ SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
+ SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
SSVAL(pdata,l1_attrFile,mode);
break;
srv_put_dos_date2(pdata,0,create_time);
srv_put_dos_date2(pdata,4,atime);
srv_put_dos_date2(pdata,8,mtime); /* write time */
- SIVAL(pdata,12,(uint32)file_size);
- SIVAL(pdata,16,(uint32)allocation_size);
+ SIVAL(pdata,12,(uint32_t)file_size);
+ SIVAL(pdata,16,(uint32_t)allocation_size);
SSVAL(pdata,20,mode);
SIVAL(pdata,22,ea_size);
break;
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",
{
SMB_ACL_T file_acl = NULL;
SMB_ACL_T def_acl = NULL;
- uint16 num_file_acls = 0;
- uint16 num_def_acls = 0;
+ uint16_t num_file_acls = 0;
+ uint16_t num_def_acls = 0;
+
+ status = refuse_symlink(conn,
+ fsp,
+ smb_fname->base_name);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
if (fsp && fsp->fh->fd != -1) {
file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
{
char *params = *pparams;
char *pdata = *ppdata;
- uint16 info_level;
+ uint16_t info_level;
unsigned int data_size = 0;
unsigned int param_size = 2;
struct smb_filename *smb_fname = NULL;
} else {
uint32_t name_hash;
char *fname = NULL;
- uint32_t ucf_flags = 0;
+ uint32_t ucf_flags = (req->posix_pathnames ?
+ UCF_POSIX_PATHNAMES : 0);
/* qpathinfo */
if (total_params < 7) {
}
}
- 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;
case SMB_INFO_QUERY_EAS_FROM_LIST:
{
/* Pull any EA list from the data portion. */
- uint32 ea_size;
+ uint32_t ea_size;
if (total_data < 4) {
reply_nterror(
bool setting_write_time)
{
struct smb_filename smb_fname_base;
- uint32 action =
+ uint32_t action =
FILE_NOTIFY_CHANGE_LAST_ACCESS
|FILE_NOTIFY_CHANGE_LAST_WRITE
|FILE_NOTIFY_CHANGE_CREATION;
static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
const struct smb_filename *smb_fname,
- uint32 dosmode)
+ uint32_t dosmode)
{
struct smb_filename *smb_fname_base;
NTSTATUS status;
NULL, /* sd */
NULL, /* ea_list */
&new_fsp, /* result */
- NULL); /* pinfo */
+ NULL, /* pinfo */
+ NULL, NULL); /* create context */
TALLOC_FREE(smb_fname_tmp);
{
NTSTATUS status = NT_STATUS_OK;
bool delete_on_close;
- uint32 dosmode = 0;
+ uint32_t dosmode = 0;
if (total_data < 1) {
return NT_STATUS_INVALID_PARAMETER;
const char *pdata,
int total_data)
{
- uint32 mode;
+ uint32_t mode;
if (total_data < 4) {
return NT_STATUS_INVALID_PARAMETER;
{
char *oldname = NULL;
struct smb_filename *smb_fname_old = NULL;
+ uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
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;
}
conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
oldname,
- 0,
+ ucf_flags,
NULL,
&smb_fname_old);
if (!NT_STATUS_IS_OK(status)) {
uint32_t len;
char *newname = NULL;
struct smb_filename *smb_fname_dst = NULL;
+ uint32_t ucf_flags = UCF_SAVE_LCOMP |
+ (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
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;
}
conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
newname,
- UCF_SAVE_LCOMP,
+ ucf_flags,
NULL,
&smb_fname_dst);
if (!NT_STATUS_IS_OK(status)) {
char *newname = NULL;
struct smb_filename *smb_fname_dst = NULL;
NTSTATUS status = NT_STATUS_OK;
+ uint32_t ucf_flags = UCF_SAVE_LCOMP |
+ (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
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;
}
conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
newname,
- UCF_SAVE_LCOMP,
+ ucf_flags,
NULL,
&smb_fname_dst);
if (!NT_STATUS_IS_OK(status)) {
struct smb_filename *smb_fname_src)
{
bool overwrite;
- uint32 root_fid;
- uint32 len;
+ uint32_t root_fid;
+ uint32_t len;
char *newname = NULL;
struct smb_filename *smb_fname_dst = NULL;
bool dest_has_wcard = False;
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;
}
files_struct *fsp,
const struct smb_filename *smb_fname)
{
- uint16 posix_acl_version;
- uint16 num_file_acls;
- uint16 num_def_acls;
+ uint16_t posix_acl_version;
+ uint16_t num_file_acls;
+ 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->base_name);
+ 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,
{
/* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
struct smb_file_time ft;
- uint32 dosmode = 0;
+ uint32_t dosmode = 0;
NTSTATUS status = NT_STATUS_OK;
ZERO_STRUCT(ft);
NULL, /* sd */
NULL, /* ea_list */
&new_fsp, /* result */
- NULL); /* pinfo */
+ NULL, /* pinfo */
+ NULL, NULL); /* create context */
if (!NT_STATUS_IS_OK(status)) {
/* NB. We check for open_was_deferred in the caller. */
int total_data,
const struct smb_filename *smb_fname)
{
- uint32 file_type = IVAL(pdata,56);
+ uint32_t file_type = IVAL(pdata,56);
#if defined(HAVE_MAKEDEV)
- uint32 dev_major = IVAL(pdata,60);
- uint32 dev_minor = IVAL(pdata,68);
+ uint32_t dev_major = IVAL(pdata,60);
+ uint32_t dev_minor = IVAL(pdata,68);
#endif
SMB_DEV_T dev = (SMB_DEV_T)0;
- uint32 raw_unixmode = IVAL(pdata,84);
+ uint32_t raw_unixmode = IVAL(pdata,84);
NTSTATUS status;
mode_t unixmode;
const struct smb_filename *smb_fname)
{
struct smb_file_time ft;
- uint32 raw_unixmode;
+ uint32_t raw_unixmode;
mode_t unixmode;
off_t size = 0;
uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
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);
}
* 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) {
const struct smb_filename *smb_fname)
{
NTSTATUS status;
- uint32 smb_fflags;
- uint32 smb_fmask;
+ uint32_t smb_fflags;
+ uint32_t smb_fmask;
if (total_data < 116) {
return NT_STATUS_INVALID_PARAMETER;
int *pdata_return_size)
{
NTSTATUS status = NT_STATUS_OK;
- uint32 raw_unixmode = 0;
- uint32 mod_unixmode = 0;
+ uint32_t raw_unixmode = 0;
+ uint32_t mod_unixmode = 0;
mode_t unixmode = (mode_t)0;
files_struct *fsp = NULL;
- uint16 info_level_return = 0;
+ uint16_t info_level_return = 0;
int info;
char *pdata = *ppdata;
return status;
}
- mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
+ mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
NULL, /* sd */
NULL, /* ea_list */
&fsp, /* result */
- &info); /* pinfo */
+ &info, /* pinfo */
+ NULL, NULL); /* create context */
if (NT_STATUS_IS_OK(status)) {
close_file(req, fsp, NORMAL_CLOSE);
{
bool extended_oplock_granted = False;
char *pdata = *ppdata;
- uint32 flags = 0;
- uint32 wire_open_mode = 0;
- uint32 raw_unixmode = 0;
- uint32 mod_unixmode = 0;
- uint32 create_disp = 0;
- uint32 access_mask = 0;
- uint32 create_options = FILE_NON_DIRECTORY_FILE;
+ uint32_t flags = 0;
+ uint32_t wire_open_mode = 0;
+ uint32_t raw_unixmode = 0;
+ uint32_t mod_unixmode = 0;
+ uint32_t create_disp = 0;
+ uint32_t access_mask = 0;
+ uint32_t create_options = FILE_NON_DIRECTORY_FILE;
NTSTATUS status = NT_STATUS_OK;
mode_t unixmode = (mode_t)0;
files_struct *fsp = NULL;
int oplock_request = 0;
int info = 0;
- uint16 info_level_return = 0;
+ uint16_t info_level_return = 0;
if (total_data < 18) {
return NT_STATUS_INVALID_PARAMETER;
return status;
}
- mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
+ mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
if (wire_open_mode & SMB_O_SYNC) {
create_options |= FILE_WRITE_THROUGH;
NULL, /* sd */
NULL, /* ea_list */
&fsp, /* result */
- &info); /* pinfo */
+ &info, /* pinfo */
+ NULL, NULL); /* create context */
if (!NT_STATUS_IS_OK(status)) {
return status;
{
NTSTATUS status = NT_STATUS_OK;
files_struct *fsp = NULL;
- uint16 flags = 0;
+ uint16_t flags = 0;
char del = 1;
int info = 0;
int create_options = 0;
NULL, /* sd */
NULL, /* ea_list */
&fsp, /* result */
- &info); /* pinfo */
+ &info, /* pinfo */
+ NULL, NULL); /* create context */
if (!NT_STATUS_IS_OK(status)) {
return status;
{
char *params = *pparams;
char *pdata = *ppdata;
- uint16 info_level;
+ uint16_t info_level;
struct smb_filename *smb_fname = NULL;
files_struct *fsp = NULL;
NTSTATUS status = NT_STATUS_OK;
}
} else {
char *fname = NULL;
- uint32_t ucf_flags = 0;
+ uint32_t ucf_flags = (req->posix_pathnames ?
+ UCF_POSIX_PATHNAMES : 0);
/* 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;
ppdata, total_data,
&data_return_size);
if (!NT_STATUS_IS_OK(status)) {
- if (open_was_deferred(req->sconn, req->mid)) {
+ if (open_was_deferred(req->xconn, req->mid)) {
/* We have re-scheduled this call. */
return;
}
char *directory = NULL;
NTSTATUS status = NT_STATUS_OK;
struct ea_list *ea_list = NULL;
+ uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
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;
conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
directory,
- 0,
+ ucf_flags,
NULL,
&smb_dname);
unsigned int max_data_bytes)
{
char *params = *pparams;
- uint16 info_level;
+ uint16_t info_level;
if (total_params < 6) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);