summaryrefslogtreecommitdiff
path: root/source3/smbd/trans2.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd/trans2.c')
-rw-r--r--source3/smbd/trans2.c782
1 files changed, 399 insertions, 383 deletions
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 01b0130a38..9b15698744 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -31,12 +31,13 @@
#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 "smbprofile.h"
#include "rpc_server/srv_pipe_hnd.h"
-#include "libsmb/libsmb.h"
+#include "printing.h"
#define DIR_ENTRY_SAFETY_MARGIN 4096
@@ -51,6 +52,30 @@ static char *store_file_unix_basic_info2(connection_struct *conn,
const SMB_STRUCT_STAT *psbuf);
/********************************************************************
+ The canonical "check access" based on object handle or path function.
+********************************************************************/
+
+NTSTATUS check_access(connection_struct *conn,
+ files_struct *fsp,
+ const struct smb_filename *smb_fname,
+ uint32_t access_mask)
+{
+ if (fsp) {
+ if (!(fsp->access_mask & access_mask)) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ } else {
+ NTSTATUS status = smbd_check_access_rights(conn,
+ smb_fname,
+ access_mask);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+/********************************************************************
Roundup a value to the nearest allocation roundup size boundary.
Only do this for Windows clients.
********************************************************************/
@@ -108,7 +133,7 @@ static bool samba_private_attr_name(const char *unix_ea_name)
if (strequal( prohibited_ea_names[i], unix_ea_name))
return true;
}
- if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
+ if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
return true;
}
@@ -130,7 +155,7 @@ NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
again:
- val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
+ val = talloc_realloc(mem_ctx, val, char, attr_size);
if (!val) {
return NT_STATUS_NO_MEMORY;
}
@@ -193,7 +218,7 @@ NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
* TALLOC the result early to get the talloc hierarchy right.
*/
- names = TALLOC_ARRAY(mem_ctx, char *, 1);
+ names = talloc_array(mem_ctx, char *, 1);
if (names == NULL) {
DEBUG(0, ("talloc failed\n"));
return NT_STATUS_NO_MEMORY;
@@ -201,7 +226,7 @@ NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
while (ea_namelist_size <= 65536) {
- ea_namelist = TALLOC_REALLOC_ARRAY(
+ ea_namelist = talloc_realloc(
names, ea_namelist, char, ea_namelist_size);
if (ea_namelist == NULL) {
DEBUG(0, ("talloc failed\n"));
@@ -260,7 +285,7 @@ NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
num_names += 1;
}
- tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
+ tmp = talloc_realloc(mem_ctx, names, char *, num_names);
if (tmp == NULL) {
DEBUG(0, ("talloc failed\n"));
TALLOC_FREE(names);
@@ -287,8 +312,8 @@ NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
Return a linked list of the total EA's. Plus the total size
****************************************************************************/
-static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
- const char *fname, size_t *pea_total_len)
+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)
{
/* Get a list of all xattrs. Max namesize is 64k. */
size_t i, num_names;
@@ -298,15 +323,16 @@ static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_str
*pea_total_len = 0;
- if (!lp_ea_support(SNUM(conn))) {
- return NULL;
- }
-
status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
&names, &num_names);
- if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
- return NULL;
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ if (num_names == 0) {
+ *ea_list = NULL;
+ return NT_STATUS_OK;
}
for (i=0; i<num_names; i++) {
@@ -317,24 +343,17 @@ static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_str
|| samba_private_attr_name(names[i]))
continue;
- listp = TALLOC_P(mem_ctx, struct ea_list);
+ listp = talloc(mem_ctx, struct ea_list);
if (listp == NULL) {
- return NULL;
+ return NT_STATUS_NO_MEMORY;
}
- if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
- fname, names[i],
- &listp->ea))) {
- return NULL;
- }
+ status = get_ea_value(mem_ctx, conn, fsp,
+ fname, names[i],
+ &listp->ea);
- if (listp->ea.value.length == 0) {
- /*
- * We can never return a zero length EA.
- * Windows reports the EA's as corrupted.
- */
- TALLOC_FREE(listp);
- continue;
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
push_ascii_fstring(dos_ea_name, listp->ea.name);
@@ -358,7 +377,25 @@ static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_str
DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
(unsigned int)*pea_total_len));
- return ea_list_head;
+ *ea_list = ea_list_head;
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS get_ea_list_from_file(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)
+{
+ *pea_total_len = 0;
+ *ea_list = NULL;
+
+ if (!lp_ea_support(SNUM(conn))) {
+ return NT_STATUS_OK;
+ }
+
+ if (is_ntfs_stream_smb_fname(smb_fname)) {
+ 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);
}
/****************************************************************************
@@ -398,7 +435,7 @@ static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned in
SCVAL(p,0,ea_list->ea.flags);
SCVAL(p,1,dos_namelen);
SSVAL(p,2,ea_list->ea.value.length);
- fstrcpy(p+4, dos_ea_name);
+ strlcpy(p+4, dos_ea_name, dos_namelen+1);
memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
@@ -420,7 +457,6 @@ static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
{
uint8_t *p = (uint8_t *)pdata;
uint8_t *last_start = NULL;
- bool store_data = (pdata != NULL);
*ret_data_size = 0;
@@ -432,9 +468,8 @@ static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
size_t dos_namelen;
fstring dos_ea_name;
size_t this_size;
- size_t pad = 0;
- if (last_start && store_data) {
+ if (last_start) {
SIVAL(last_start, 0, PTR_DIFF(p, last_start));
}
last_start = p;
@@ -451,7 +486,7 @@ static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
if (ea_list->next) {
- pad = (4 - (this_size % 4)) % 4;
+ size_t pad = 4 - (this_size % 4);
this_size += pad;
}
@@ -460,19 +495,12 @@ static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
}
/* We know we have room. */
- if (store_data) {
- SIVAL(p, 0x00, 0); /* next offset */
- SCVAL(p, 0x04, ea_list->ea.flags);
- SCVAL(p, 0x05, dos_namelen);
- SSVAL(p, 0x06, ea_list->ea.value.length);
- fstrcpy((char *)(p+0x08), dos_ea_name);
- memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
- if (pad) {
- memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
- '\0',
- pad);
- }
- }
+ SIVAL(p, 0x00, 0); /* next offset */
+ SCVAL(p, 0x04, ea_list->ea.flags);
+ SCVAL(p, 0x05, dos_namelen);
+ SSVAL(p, 0x06, ea_list->ea.value.length);
+ strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
+ memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
total_data_size -= this_size;
p += this_size;
@@ -483,41 +511,26 @@ static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
return NT_STATUS_OK;
}
-static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
+static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
{
size_t total_ea_len = 0;
- struct ea_list *ea_list = NULL;
- TALLOC_CTX *mem_ctx = NULL;
+ TALLOC_CTX *mem_ctx;
+ struct ea_list *ea_list;
if (!lp_ea_support(SNUM(conn))) {
return 0;
}
- mem_ctx = talloc_tos();
- ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
- if (ea_list == NULL) {
- return 0;
- }
- if(conn->sconn->using_smb2) {
- NTSTATUS status;
- unsigned int ret_data_size;
- /*
- * We're going to be using fill_ea_chained_buffer() to
- * marshall EA's - this size is significantly larger
- * than the SMB1 buffer. Re-calculate the size without
- * marshalling.
- */
- status = fill_ea_chained_buffer(mem_ctx,
- NULL,
- 65535,
- &ret_data_size,
- conn,
- ea_list);
- if (!NT_STATUS_IS_OK(status)) {
- ret_data_size = 0;
- }
- total_ea_len = ret_data_size;
- }
+ mem_ctx = talloc_stackframe();
+ /* If this is a stream fsp, then we need to instead find the
+ * estimated ea len from the main file, not the stream
+ * (streams cannot have EAs), but the estimate isn't just 0 in
+ * this case! */
+ 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);
+ TALLOC_FREE(mem_ctx);
return total_ea_len;
}
@@ -529,13 +542,17 @@ static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, con
{
size_t total_ea_len;
TALLOC_CTX *mem_ctx = talloc_tos();
- struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
+ struct ea_list *ea_list;
+ NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
+ if (!NT_STATUS_IS_OK(status)) {
+ return;
+ }
for (; ea_list; ea_list = ea_list->next) {
if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
&unix_ea_name[5], ea_list->ea.name));
- safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
+ strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
break;
}
}
@@ -548,17 +565,23 @@ static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, con
NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
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;
}
- if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
- return NT_STATUS_ACCESS_DENIED;
+ status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ /* Setting EAs on streams isn't supported. */
+ if (is_ntfs_stream_smb_fname(smb_fname)) {
+ return NT_STATUS_INVALID_PARAMETER;
}
- /* For now setting EAs on streams isn't supported. */
fname = smb_fname->base_name;
for (;ea_list; ea_list = ea_list->next) {
@@ -634,7 +657,7 @@ static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, siz
size_t converted_size, offset = 0;
while (offset + 2 < data_size) {
- struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
+ struct ea_list *eal = talloc_zero(ctx, struct ea_list);
unsigned int namelen = CVAL(pdata,offset);
offset++; /* Go past the namelen byte. */
@@ -672,7 +695,7 @@ static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, siz
struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
{
- struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
+ struct ea_list *eal = talloc_zero(ctx, struct ea_list);
uint16 val_len;
unsigned int namelen;
size_t converted_size;
@@ -1039,7 +1062,7 @@ static void call_trans2open(connection_struct *conn,
uint32 open_size;
char *pname;
char *fname = NULL;
- SMB_OFF_T size=0;
+ off_t size=0;
int fattr=0,mtime=0;
SMB_INO_T inode = 0;
int smb_action = 0;
@@ -1176,7 +1199,7 @@ static void call_trans2open(connection_struct *conn,
&smb_action); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
- if (open_was_deferred(req->mid)) {
+ if (open_was_deferred(req->sconn, req->mid)) {
/* We have re-scheduled this call. */
goto out;
}
@@ -1223,7 +1246,7 @@ static void call_trans2open(connection_struct *conn,
SSVAL(params,24,0); /* Padding. */
if (flags & 8) {
uint32 ea_size = estimate_ea_size(conn, fsp,
- fsp->fsp_name->base_name);
+ smb_fname);
SIVAL(params, 26, ea_size);
} else {
SIVAL(params, 26, 0);
@@ -1258,7 +1281,7 @@ static bool exact_match(bool has_wild,
if (case_sensitive) {
return strcmp(str,mask)==0;
} else {
- return StrCaseCmp(str,mask) == 0;
+ return strcasecmp_m(str,mask) == 0;
}
}
@@ -1341,28 +1364,18 @@ static NTSTATUS unix_perms_from_wire( connection_struct *conn,
switch (ptype) {
case PERM_NEW_FILE:
+ case PERM_EXISTING_FILE:
/* Apply mode mask */
ret &= lp_create_mask(SNUM(conn));
/* Add in force bits */
ret |= lp_force_create_mode(SNUM(conn));
break;
case PERM_NEW_DIR:
+ case PERM_EXISTING_DIR:
ret &= lp_dir_mask(SNUM(conn));
/* Add in force bits */
ret |= lp_force_dir_mode(SNUM(conn));
break;
- case PERM_EXISTING_FILE:
- /* Apply mode mask */
- ret &= lp_security_mask(SNUM(conn));
- /* Add in force bits */
- ret |= lp_force_security_mode(SNUM(conn));
- break;
- case PERM_EXISTING_DIR:
- /* Apply mode mask */
- ret &= lp_dir_security_mask(SNUM(conn));
- /* Add in force bits */
- ret |= lp_force_dir_security_mode(SNUM(conn));
- break;
}
*ret_perms = ret;
@@ -1550,7 +1563,6 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
uint32_t len;
struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
- time_t c_date = (time_t)0;
char *nameptr;
char *last_entry_ptr;
bool was_8_3;
@@ -1586,7 +1598,6 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
create_date = convert_timespec_to_time_t(create_date_ts);
mdate = convert_timespec_to_time_t(mdate_ts);
adate = convert_timespec_to_time_t(adate_ts);
- c_date = convert_timespec_to_time_t(cdate_ts);
/* align the record */
SMB_ASSERT(align >= 1);
@@ -1672,7 +1683,7 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
SSVAL(p,20,mode);
{
unsigned int ea_size = estimate_ea_size(conn, NULL,
- smb_fname->base_name);
+ smb_fname);
SIVAL(p,22,ea_size); /* Extended attributes */
}
p += 27;
@@ -1702,6 +1713,7 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
{
struct ea_list *file_list = NULL;
size_t ea_len = 0;
+ NTSTATUS status;
DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
if (!name_list) {
@@ -1719,9 +1731,12 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
SSVAL(p,20,mode);
p += 22; /* p now points to the EA area. */
- file_list = get_ea_list_from_file(ctx, conn, NULL,
- smb_fname->base_name,
- &ea_len);
+ status = get_ea_list_from_file(ctx, conn, NULL,
+ smb_fname,
+ &ea_len, &file_list);
+ if (!NT_STATUS_IS_OK(status)) {
+ file_list = NULL;
+ }
name_list = ea_list_union(name_list, file_list, &ea_len);
/* We need to determine if this entry will fit in the space available. */
@@ -1775,7 +1790,7 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
q = p; p += 4; /* q is placeholder for name length. */
{
unsigned int ea_size = estimate_ea_size(conn, NULL,
- smb_fname->base_name);
+ smb_fname);
SIVAL(p,0,ea_size); /* Extended attributes */
p += 4;
}
@@ -1877,7 +1892,7 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
q = p; p += 4; /* q is placeholder for name length. */
{
unsigned int ea_size = estimate_ea_size(conn, NULL,
- smb_fname->base_name);
+ smb_fname);
SIVAL(p,0,ea_size); /* Extended attributes */
p +=4;
}
@@ -1952,7 +1967,7 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
q = p; p += 4; /* q is placeholder for name length. */
{
unsigned int ea_size = estimate_ea_size(conn, NULL,
- smb_fname->base_name);
+ smb_fname);
SIVAL(p,0,ea_size); /* Extended attributes */
p +=4;
}
@@ -1998,7 +2013,7 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
q = p; p += 4; /* q is placeholder for name length */
{
unsigned int ea_size = estimate_ea_size(conn, NULL,
- smb_fname->base_name);
+ smb_fname);
SIVAL(p,0,ea_size); /* Extended attributes */
p +=4;
}
@@ -2309,6 +2324,7 @@ static void call_trans2findfirst(connection_struct *conn,
struct dptr_struct *dirptr = NULL;
struct smbd_server_connection *sconn = req->sconn;
uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
+ bool backup_priv = false;
if (total_params < 13) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
@@ -2321,11 +2337,16 @@ static void call_trans2findfirst(connection_struct *conn,
close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
+ backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
+ security_token_has_privilege(get_current_nttok(conn),
+ SEC_PRIV_BACKUP));
+
info_level = SVAL(params,6);
DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
-close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
+close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
(unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
+ (int)backup_priv,
info_level, max_data_bytes));
if (!maxentries) {
@@ -2367,12 +2388,24 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
goto out;
}
- ntstatus = filename_convert(ctx, conn,
+ if (backup_priv) {
+ become_root();
+ ntstatus = filename_convert_with_privilege(ctx,
+ conn,
+ req,
+ directory,
+ ucf_flags,
+ &mask_contains_wcard,
+ &smb_dname);
+ } else {
+ ntstatus = filename_convert(ctx, conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
directory,
ucf_flags,
&mask_contains_wcard,
&smb_dname);
+ }
+
if (!NT_STATUS_IS_OK(ntstatus)) {
if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
@@ -2463,6 +2496,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
needed as lanman2 assumes these are being saved between calls */
ntstatus = dptr_create(conn,
+ req,
NULL, /* fsp */
directory,
False,
@@ -2478,6 +2512,12 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
goto out;
}
+ if (backup_priv) {
+ /* Remember this in case we have
+ to do a findnext. */
+ dptr_set_priv(dirptr);
+ }
+
dptr_num = dptr_dnum(dirptr);
DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
@@ -2488,8 +2528,8 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
a different TRANS2 call. */
DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
- directory,lp_dontdescend(SNUM(conn))));
- if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
+ directory,lp_dontdescend(ctx, SNUM(conn))));
+ if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
dont_descend = True;
p = pdata;
@@ -2604,6 +2644,11 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
name_to_8_3(mask, mangled_name, True, conn->params);
}
out:
+
+ if (backup_priv) {
+ unbecome_root();
+ }
+
TALLOC_FREE(smb_dname);
return;
}
@@ -2653,6 +2698,7 @@ static void call_trans2findnext(connection_struct *conn,
TALLOC_CTX *ctx = talloc_tos();
struct dptr_struct *dirptr;
struct smbd_server_connection *sconn = req->sconn;
+ bool backup_priv = false;
if (total_params < 13) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
@@ -2786,21 +2832,23 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
directory = dptr_path(sconn, dptr_num);
/* Get the wildcard mask from the dptr */
- if((p = dptr_wcard(sconn, dptr_num))== NULL) {
+ if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
reply_nterror(req, STATUS_NO_MORE_FILES);
return;
}
- mask = p;
-
/* Get the attr mask from the dptr */
dirtype = dptr_attr(sconn, dptr_num);
- DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
+ backup_priv = dptr_get_priv(dirptr);
+
+ DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
+ "backup_priv = %d\n",
dptr_num, mask, dirtype,
(long)dirptr,
- dptr_TellDir(dirptr)));
+ dptr_TellDir(dirptr),
+ (int)backup_priv));
/* Initialize per TRANS2_FIND_NEXT operation data */
dptr_init_search_op(dirptr);
@@ -2809,14 +2857,18 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
a different TRANS2 call. */
DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
- directory,lp_dontdescend(SNUM(conn))));
- if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
+ directory,lp_dontdescend(ctx, SNUM(conn))));
+ if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
dont_descend = True;
p = pdata;
space_remaining = max_data_bytes;
out_of_space = False;
+ if (backup_priv) {
+ become_root();
+ }
+
/*
* Seek to the correct position. We no longer use the resume key but
* depend on the last file name instead.
@@ -2906,6 +2958,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
}
+ if (backup_priv) {
+ unbecome_root();
+ }
+
/* Set up the return parameter block */
SSVAL(params,0,numentries);
SSVAL(params,2,finished);
@@ -2920,7 +2976,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
{
- E_md4hash(lp_servicename(SNUM(conn)),objid);
+ E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
return objid;
}
@@ -2964,26 +3020,18 @@ NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
uint16_t info_level,
uint16_t flags2,
unsigned int max_data_bytes,
- struct smb_filename *fname,
char **ppdata,
int *ret_data_len)
{
char *pdata, *end_data;
int data_len = 0, len;
- const char *vname = volume_label(SNUM(conn));
+ const char *vname = volume_label(talloc_tos(), SNUM(conn));
int snum = SNUM(conn);
- char *fstype = lp_fstype(SNUM(conn));
- const char *filename = NULL;
+ char *fstype = lp_fstype(talloc_tos(), SNUM(conn));
uint32 additional_flags = 0;
- struct smb_filename smb_fname;
+ struct smb_filename smb_fname_dot;
SMB_STRUCT_STAT st;
- if (fname == NULL || fname->base_name == NULL) {
- filename = ".";
- } else {
- filename = fname->base_name;
- }
-
if (IS_IPC(conn)) {
if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
DEBUG(0,("smbd_do_qfsinfo: not an allowed "
@@ -2995,15 +3043,15 @@ NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
- ZERO_STRUCT(smb_fname);
- smb_fname.base_name = discard_const_p(char, filename);
+ ZERO_STRUCT(smb_fname_dot);
+ smb_fname_dot.base_name = discard_const_p(char, ".");
- if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
+ if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
return map_nt_error_from_unix(errno);
}
- st = smb_fname.st;
+ st = smb_fname_dot.st;
*ppdata = (char *)SMB_REALLOC(
*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
@@ -3020,7 +3068,7 @@ NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
{
uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
data_len = 18;
- if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
+ if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
return map_nt_error_from_unix(errno);
}
@@ -3058,7 +3106,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u
* Add volume serial number - hash of a combination of
* the called hostname and the service name.
*/
- SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
+ SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
/*
* Win2k3 and previous mess this up by sending a name length
* one byte short. I believe only older clients (OS/2 Win9x) use
@@ -3124,7 +3172,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u
* Add volume serial number - hash of a combination of
* the called hostname and the service name.
*/
- SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
+ SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
(str_checksum(get_local_machine_name())<<16));
/* Max label len is 32 characters. */
@@ -3135,7 +3183,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u
data_len = 18+len;
DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
- (int)strlen(vname),vname, lp_servicename(snum)));
+ (int)strlen(vname),vname,
+ lp_servicename(talloc_tos(), snum)));
break;
case SMB_QUERY_FS_SIZE_INFO:
@@ -3143,7 +3192,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (u
{
uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
data_len = 24;
- if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
+ if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
return map_nt_error_from_unix(errno);
}
block_size = lp_block_size(snum);
@@ -3175,7 +3224,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
{
uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
data_len = 32;
- if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
+ if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
return map_nt_error_from_unix(errno);
}
block_size = lp_block_size(snum);
@@ -3250,26 +3299,26 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
ZERO_STRUCT(quotas);
fsp.conn = conn;
- fsp.fnum = -1;
+ fsp.fnum = FNUM_FIELD_INVALID;
/* access check */
if (get_current_uid(conn) != 0) {
DEBUG(0,("set_user_quota: access_denied "
"service [%s] user [%s]\n",
- lp_servicename(SNUM(conn)),
- conn->session_info->unix_name));
+ lp_servicename(talloc_tos(), SNUM(conn)),
+ conn->session_info->unix_info->unix_name));
return NT_STATUS_ACCESS_DENIED;
}
if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
- DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
+ DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
return map_nt_error_from_unix(errno);
}
data_len = 48;
DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
- lp_servicename(SNUM(conn))));
+ lp_servicename(talloc_tos(), SNUM(conn))));
/* Unknown1 24 NULL bytes*/
SBIG_UINT(pdata,0,(uint64_t)0);
@@ -3324,14 +3373,14 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
}
switch (conn->encrypt_level) {
- case 0:
+ case SMB_SIGNING_OFF:
encrypt_caps = 0;
break;
- case 1:
- case Auto:
+ case SMB_SIGNING_IF_REQUIRED:
+ case SMB_SIGNING_DEFAULT:
encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
break;
- case Required:
+ case SMB_SIGNING_REQUIRED:
encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
large_write = false;
@@ -3368,7 +3417,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
return NT_STATUS_INVALID_LEVEL;
}
- rc = SMB_VFS_STATVFS(conn, filename, &svfs);
+ rc = SMB_VFS_STATVFS(conn, ".", &svfs);
if (!rc) {
data_len = 56;
@@ -3386,7 +3435,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
return NT_STATUS_INVALID_LEVEL;
#endif /* EOPNOTSUPP */
} else {
- DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
+ DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
return NT_STATUS_DOS(ERRSRV, ERRerror);
}
break;
@@ -3406,22 +3455,10 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
return NT_STATUS_BUFFER_TOO_SMALL;
}
- /* We ARE guest if global_sid_Builtin_Guests is
- * in our list of SIDs.
- */
- if (nt_token_check_sid(&global_sid_Builtin_Guests,
- conn->session_info->security_token)) {
+ if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
flags |= SMB_WHOAMI_GUEST;
}
- /* We are NOT guest if global_sid_Authenticated_Users
- * is in our list of SIDs.
- */
- if (nt_token_check_sid(&global_sid_Authenticated_Users,
- conn->session_info->security_token)) {
- flags &= ~SMB_WHOAMI_GUEST;
- }
-
/* NOTE: 8 bytes for UID/GID, irrespective of native
* platform size. This matches
* SMB_QUERY_FILE_UNIX_BASIC and friends.
@@ -3434,7 +3471,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
+ 4 /* num_sids */
+ 4 /* SID bytes */
+ 4 /* pad/reserved */
- + (conn->session_info->utok.ngroups * 8)
+ + (conn->session_info->unix_token->ngroups * 8)
/* groups list */
+ (conn->session_info->security_token->num_sids *
SID_MAX_SIZE)
@@ -3443,9 +3480,9 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
SIVAL(pdata, 0, flags);
SIVAL(pdata, 4, SMB_WHOAMI_MASK);
SBIG_UINT(pdata, 8,
- (uint64_t)conn->session_info->utok.uid);
+ (uint64_t)conn->session_info->unix_token->uid);
SBIG_UINT(pdata, 16,
- (uint64_t)conn->session_info->utok.gid);
+ (uint64_t)conn->session_info->unix_token->gid);
if (data_len >= max_data_bytes) {
@@ -3460,7 +3497,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
break;
}
- SIVAL(pdata, 24, conn->session_info->utok.ngroups);
+ SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
/* We walk the SID list twice, but this call is fairly
@@ -3482,9 +3519,9 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
data_len = 40;
/* GID list */
- for (i = 0; i < conn->session_info->utok.ngroups; ++i) {
+ for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
SBIG_UINT(pdata, data_len,
- (uint64_t)conn->session_info->utok.groups[i]);
+ (uint64_t)conn->session_info->unix_token->groups[i]);
data_len += 8;
}
@@ -3508,7 +3545,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
* Thursby MAC extension... ONLY on NTFS filesystems
* once we do streams then we don't need this
*/
- if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
+ if (strequal(lp_fstype(talloc_tos(), SNUM(conn)),"NTFS")) {
data_len = 88;
SIVAL(pdata,84,0x100); /* Don't support mac... */
break;
@@ -3549,8 +3586,7 @@ static void call_trans2qfsinfo(connection_struct *conn,
DEBUG(0,("call_trans2qfsinfo: encryption required "
"and info level 0x%x sent.\n",
(unsigned int)info_level));
- exit_server_cleanly("encryption required "
- "on connection");
+ reply_nterror(req, NT_STATUS_ACCESS_DENIED);
return;
}
}
@@ -3561,7 +3597,6 @@ static void call_trans2qfsinfo(connection_struct *conn,
info_level,
req->flags2,
max_data_bytes,
- NULL,
ppdata, &data_len);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
@@ -3587,11 +3622,13 @@ static void call_trans2setfsinfo(connection_struct *conn,
char **ppdata, int total_data,
unsigned int max_data_bytes)
{
+ struct smbd_server_connection *sconn = req->sconn;
char *pdata = *ppdata;
char *params = *pparams;
uint16 info_level;
- DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
+ DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
+ lp_servicename(talloc_tos(), SNUM(conn))));
/* */
if (total_params < 4) {
@@ -3619,62 +3656,62 @@ static void call_trans2setfsinfo(connection_struct *conn,
DEBUG(0,("call_trans2setfsinfo: encryption required "
"and info level 0x%x sent.\n",
(unsigned int)info_level));
- exit_server_cleanly("encryption required "
- "on connection");
+ reply_nterror(req, NT_STATUS_ACCESS_DENIED);
return;
}
}
switch(info_level) {
case SMB_SET_CIFS_UNIX_INFO:
- {
- uint16 client_unix_major;
- uint16 client_unix_minor;
- uint32 client_unix_cap_low;
- uint32 client_unix_cap_high;
-
- if (!lp_unix_extensions()) {
- reply_nterror(req,
- NT_STATUS_INVALID_LEVEL);
- return;
- }
+ if (!lp_unix_extensions()) {
+ DEBUG(2,("call_trans2setfsinfo: "
+ "SMB_SET_CIFS_UNIX_INFO is invalid with "
+ "unix extensions off\n"));
+ reply_nterror(req,
+ NT_STATUS_INVALID_LEVEL);
+ return;
+ }
- /* There should be 12 bytes of capabilities set. */
- if (total_data < 8) {
- reply_nterror(
- req,
- NT_STATUS_INVALID_PARAMETER);
- return;
- }
- client_unix_major = SVAL(pdata,0);
- client_unix_minor = SVAL(pdata,2);
- client_unix_cap_low = IVAL(pdata,4);
- client_unix_cap_high = IVAL(pdata,8);
- /* Just print these values for now. */
- DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
-cap_low = 0x%x, cap_high = 0x%x\n",
- (unsigned int)client_unix_major,
- (unsigned int)client_unix_minor,
- (unsigned int)client_unix_cap_low,
- (unsigned int)client_unix_cap_high ));
-
- /* Here is where we must switch to posix pathname processing... */
- if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
- lp_set_posix_pathnames();
- mangle_change_to_posix();
- }
+ /* There should be 12 bytes of capabilities set. */
+ if (total_data < 12) {
+ reply_nterror(
+ req,
+ NT_STATUS_INVALID_PARAMETER);
+ return;
+ }
+ sconn->smb1.unix_info.client_major = SVAL(pdata,0);
+ sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
+ sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
+ sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
+ /* Just print these values for now. */
+ DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
+ "major = %u, minor = %u cap_low = 0x%x, "
+ "cap_high = 0x%xn",
+ (unsigned int)sconn->
+ smb1.unix_info.client_major,
+ (unsigned int)sconn->
+ smb1.unix_info.client_minor,
+ (unsigned int)sconn->
+ smb1.unix_info.client_cap_low,
+ (unsigned int)sconn->
+ smb1.unix_info.client_cap_high));
+
+ /* Here is where we must switch to posix pathname processing... */
+ if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
+ lp_set_posix_pathnames();
+ mangle_change_to_posix();
+ }
- if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
- !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
- /* Client that knows how to do posix locks,
- * but not posix open/mkdir operations. Set a
- * default type for read/write checks. */
+ if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
+ !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
+ /* Client that knows how to do posix locks,
+ * but not posix open/mkdir operations. Set a
+ * default type for read/write checks. */
- lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
+ lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
- }
- break;
}
+ break;
case SMB_REQUEST_TRANSPORT_ENCRYPTION:
{
@@ -3689,7 +3726,7 @@ cap_low = 0x%x, cap_high = 0x%x\n",
return;
}
- if (lp_smb_encrypt(SNUM(conn)) == false) {
+ if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
reply_nterror(
req,
NT_STATUS_NOT_SUPPORTED);
@@ -3733,9 +3770,11 @@ cap_low = 0x%x, cap_high = 0x%x\n",
* encryption is now *on*. */
status = srv_encryption_start(conn);
if (!NT_STATUS_IS_OK(status)) {
- exit_server_cleanly(
- "Failure in setting "
- "up encrypted transport");
+ char *reason = talloc_asprintf(talloc_tos(),
+ "Failure in setting "
+ "up encrypted transport: %s",
+ nt_errstr(status));
+ exit_server_cleanly(reason);
}
}
return;
@@ -3751,8 +3790,8 @@ cap_low = 0x%x, cap_high = 0x%x\n",
/* 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(SNUM(conn)),
- conn->session_info->unix_name));
+ lp_servicename(talloc_tos(), SNUM(conn)),
+ conn->session_info->unix_info->unix_name));
reply_nterror(req, NT_STATUS_ACCESS_DENIED);
return;
}
@@ -3795,7 +3834,7 @@ cap_low = 0x%x, cap_high = 0x%x\n",
/* now set the quotas */
if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
- DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
+ 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));
return;
}
@@ -3830,7 +3869,7 @@ static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_a
int entry_id = SMB_ACL_FIRST_ENTRY;
SMB_ACL_ENTRY_T entry;
- while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
+ while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
/* get_next... */
if (entry_id == SMB_ACL_FIRST_ENTRY) {
entry_id = SMB_ACL_NEXT_ENTRY;
@@ -3849,7 +3888,7 @@ static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_
int entry_id = SMB_ACL_FIRST_ENTRY;
SMB_ACL_ENTRY_T entry;
- while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
+ while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
SMB_ACL_TAG_T tagtype;
SMB_ACL_PERMSET_T permset;
unsigned char perms = 0;
@@ -3860,19 +3899,19 @@ static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_
entry_id = SMB_ACL_NEXT_ENTRY;
}
- if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
+ if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
return False;
}
- if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
+ if (sys_acl_get_permset(entry, &permset) == -1) {
DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
return False;
}
- perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
- perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
- perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
+ perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
+ perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
+ perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
SCVAL(pdata,1,perms);
@@ -3885,13 +3924,12 @@ static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_
break;
case SMB_ACL_USER:
{
- uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
+ uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
if (!puid) {
DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
return False;
}
own_grp = (unsigned int)*puid;
- SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
SCVAL(pdata,0,SMB_POSIX_ACL_USER);
SIVAL(pdata,2,own_grp);
SIVAL(pdata,6,0);
@@ -3905,13 +3943,12 @@ static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_
break;
case SMB_ACL_GROUP:
{
- gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
+ gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
if (!pgid) {
DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
return False;
}
own_grp = (unsigned int)*pgid;
- SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
SIVAL(pdata,2,own_grp);
SIVAL(pdata,6,0);
@@ -3948,6 +3985,7 @@ static char *store_file_unix_basic(connection_struct *conn,
const SMB_STRUCT_STAT *psbuf)
{
uint64_t file_index = get_FileIndex(conn, psbuf);
+ dev_t devno;
DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
@@ -3974,11 +4012,17 @@ static char *store_file_unix_basic(connection_struct *conn,
SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
pdata += 4;
- SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
+ if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
+ devno = psbuf->st_ex_rdev;
+ } else {
+ devno = psbuf->st_ex_dev;
+ }
+
+ SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
SIVAL(pdata,4,0);
pdata += 8;
- SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
+ SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
SIVAL(pdata,4,0);
pdata += 8;
@@ -4290,8 +4334,9 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
return NT_STATUS_INVALID_LEVEL;
}
- DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
- smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
+ DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
+ smb_fname_str_dbg(smb_fname),
+ fsp_fnum_dbg(fsp),
info_level, max_data_bytes));
mode = dos_mode(conn, smb_fname);
@@ -4416,7 +4461,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
{
unsigned int ea_size =
estimate_ea_size(conn, fsp,
- smb_fname->base_name);
+ smb_fname);
DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
data_size = 26;
srv_put_dos_date2(pdata,0,create_time);
@@ -4443,13 +4488,16 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
{
size_t total_ea_len = 0;
struct ea_list *ea_file_list = NULL;
-
DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
- ea_file_list =
+ status =
get_ea_list_from_file(mem_ctx, conn, fsp,
- smb_fname->base_name,
- &total_ea_len);
+ smb_fname,
+ &total_ea_len, &ea_file_list);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
if (!ea_list || (total_ea_len > data_size)) {
@@ -4466,12 +4514,15 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
{
/* We have data_size bytes to put EA's into. */
size_t total_ea_len = 0;
-
DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
- ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
- smb_fname->base_name,
- &total_ea_len);
+ status = get_ea_list_from_file(mem_ctx, conn, fsp,
+ smb_fname,
+ &total_ea_len, &ea_list);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
if (!ea_list || (total_ea_len > data_size)) {
data_size = 4;
SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
@@ -4495,10 +4546,13 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
/*TODO: add filtering and index handling */
- ea_file_list =
- get_ea_list_from_file(mem_ctx, conn, fsp,
- smb_fname->base_name,
- &total_ea_len);
+ status =
+ get_ea_list_from_file(mem_ctx, conn, fsp,
+ smb_fname,
+ &total_ea_len, &ea_file_list);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
if (!ea_file_list) {
return NT_STATUS_NO_EAS_ON_FILE;
}
@@ -4556,7 +4610,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
case SMB_QUERY_FILE_EA_INFO:
{
unsigned int ea_size =
- estimate_ea_size(conn, fsp, smb_fname->base_name);
+ estimate_ea_size(conn, fsp, smb_fname);
DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
data_size = 4;
SIVAL(pdata,0,ea_size);
@@ -4618,7 +4672,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
{
int len;
unsigned int ea_size =
- estimate_ea_size(conn, fsp, smb_fname->base_name);
+ estimate_ea_size(conn, fsp, smb_fname);
DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
@@ -4650,7 +4704,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
{
int len;
unsigned int ea_size =
- estimate_ea_size(conn, fsp, smb_fname->base_name);
+ estimate_ea_size(conn, fsp, smb_fname);
DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
@@ -4837,7 +4891,7 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
case SMB_QUERY_FILE_UNIX_LINK:
{
int len;
- char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
+ char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
if (!buffer) {
return NT_STATUS_NO_MEMORY;
@@ -4877,12 +4931,14 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
uint16 num_def_acls = 0;
if (fsp && fsp->fh->fd != -1) {
- file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
+ 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_ACL_TYPE_ACCESS);
+ SMB_ACL_TYPE_ACCESS,
+ talloc_tos());
}
if (file_acl == NULL && no_acl_syscall_error(errno)) {
@@ -4899,13 +4955,15 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
SMB_VFS_SYS_ACL_GET_FILE(
conn,
fsp->fsp_name->base_name,
- SMB_ACL_TYPE_DEFAULT);
+ SMB_ACL_TYPE_DEFAULT,
+ talloc_tos());
} else {
def_acl =
SMB_VFS_SYS_ACL_GET_FILE(
conn,
smb_fname->base_name,
- SMB_ACL_TYPE_DEFAULT);
+ SMB_ACL_TYPE_DEFAULT,
+ talloc_tos());
}
def_acl = free_empty_sys_acl(conn, def_acl);
}
@@ -4919,10 +4977,10 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
(unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
SMB_POSIX_ACL_HEADER_SIZE) ));
if (file_acl) {
- SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
+ TALLOC_FREE(file_acl);
}
if (def_acl) {
- SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
+ TALLOC_FREE(def_acl);
}
return NT_STATUS_BUFFER_TOO_SMALL;
}
@@ -4932,28 +4990,28 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
SSVAL(pdata,4,num_def_acls);
if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
if (file_acl) {
- SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
+ TALLOC_FREE(file_acl);
}
if (def_acl) {
- SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
+ TALLOC_FREE(def_acl);
}
return NT_STATUS_INTERNAL_ERROR;
}
if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
if (file_acl) {
- SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
+ TALLOC_FREE(file_acl);
}
if (def_acl) {
- SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
+ TALLOC_FREE(def_acl);
}
return NT_STATUS_INTERNAL_ERROR;
}
if (file_acl) {
- SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
+ TALLOC_FREE(file_acl);
}
if (def_acl) {
- SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
+ TALLOC_FREE(def_acl);
}
data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
break;
@@ -5158,8 +5216,8 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
* Original code - this is an open file.
*/
if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
- DEBUG(3, ("fstat of fnum %d failed (%s)\n",
- fsp->fnum, strerror(errno)));
+ DEBUG(3, ("fstat of %s failed (%s)\n",
+ fsp_fnum_dbg(fsp), strerror(errno)));
reply_nterror(req,
map_nt_error_from_unix(errno));
return;
@@ -5323,9 +5381,10 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
}
}
- DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
+ DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
"total_data=%d\n", smb_fname_str_dbg(smb_fname),
- fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
+ fsp_fnum_dbg(fsp),
+ info_level,tran_call,total_data));
/* Pull out any data sent here before we realloc. */
switch (info_level) {
@@ -5378,7 +5437,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
}
/* Copy the lock range data. */
- lock_data = (char *)TALLOC_MEMDUP(
+ lock_data = (char *)talloc_memdup(
req, pdata, total_data);
if (!lock_data) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
@@ -5507,6 +5566,8 @@ NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
/****************************************************************************
Deal with setting the time from any of the setfilepathinfo functions.
+ NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
+ calling this function.
****************************************************************************/
NTSTATUS smb_set_file_time(connection_struct *conn,
@@ -5525,10 +5586,6 @@ NTSTATUS smb_set_file_time(connection_struct *conn,
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
- if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
- return NT_STATUS_ACCESS_DENIED;
- }
-
/* get some defaults (no modifications) if any info is zero or -1. */
if (null_timespec(ft->create_time)) {
action &= ~FILE_NOTIFY_CHANGE_CREATION;
@@ -5609,6 +5666,8 @@ NTSTATUS smb_set_file_time(connection_struct *conn,
/****************************************************************************
Deal with setting the dosmode from any of the setfilepathinfo functions.
+ NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
+ done before calling this function.
****************************************************************************/
static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
@@ -5671,7 +5730,7 @@ static NTSTATUS smb_set_file_size(connection_struct *conn,
files_struct *fsp,
const struct smb_filename *smb_fname,
const SMB_STRUCT_STAT *psbuf,
- SMB_OFF_T size,
+ off_t size,
bool fail_after_createfile)
{
NTSTATUS status = NT_STATUS_OK;
@@ -5682,10 +5741,6 @@ static NTSTATUS smb_set_file_size(connection_struct *conn,
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
- if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
- return NT_STATUS_ACCESS_DENIED;
- }
-
DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
if (size == get_file_size_stat(psbuf)) {
@@ -5697,6 +5752,10 @@ static NTSTATUS smb_set_file_size(connection_struct *conn,
if (fsp && fsp->fh->fd != -1) {
/* Handle based call. */
+ if (!(fsp->access_mask & FILE_WRITE_DATA)) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
if (vfs_set_filelen(fsp, size) == -1) {
return map_nt_error_from_unix(errno);
}
@@ -5793,10 +5852,6 @@ static NTSTATUS smb_info_set_ea(connection_struct *conn,
return NT_STATUS_INVALID_PARAMETER;
}
- if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
- return NT_STATUS_ACCESS_DENIED;
- }
-
status = set_ea(conn, fsp, smb_fname, ea_list);
return status;
@@ -5840,10 +5895,6 @@ static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
return NT_STATUS_INVALID_PARAMETER;
}
- if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
- return NT_STATUS_ACCESS_DENIED;
- }
-
status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
@@ -5895,7 +5946,7 @@ static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
/* The set is across all open files on this dev/inode pair. */
if (!set_delete_on_close(fsp, delete_on_close,
conn->session_info->security_token,
- &conn->session_info->utok)) {
+ conn->session_info->unix_token)) {
return NT_STATUS_ACCESS_DENIED;
}
return NT_STATUS_OK;
@@ -5922,14 +5973,7 @@ static NTSTATUS smb_file_position_information(connection_struct *conn,
}
position_information = (uint64_t)IVAL(pdata,0);
-#ifdef LARGE_SMB_OFF_T
position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
-#else /* LARGE_SMB_OFF_T */
- if (IVAL(pdata,4) != 0) {
- /* more than 32 bits? */
- return NT_STATUS_INVALID_PARAMETER;
- }
-#endif /* LARGE_SMB_OFF_T */
DEBUG(10,("smb_file_position_information: Set file position "
"information for file %s to %.0f\n", fsp_str_dbg(fsp),
@@ -6125,8 +6169,8 @@ static NTSTATUS smb2_file_rename_information(connection_struct *conn,
}
DEBUG(10,("smb2_file_rename_information: "
- "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
- fsp->fnum, fsp_str_dbg(fsp),
+ "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
+ fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
smb_fname_str_dbg(smb_fname_dst)));
status = rename_internals_fsp(conn, fsp, smb_fname_dst,
(FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
@@ -6193,8 +6237,8 @@ static NTSTATUS smb_file_link_information(connection_struct *conn,
}
DEBUG(10,("smb_file_link_information: "
- "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
- fsp->fnum, fsp_str_dbg(fsp),
+ "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
+ fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
smb_fname_str_dbg(smb_fname_dst)));
status = hardlink_internals(ctx,
conn,
@@ -6254,6 +6298,7 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
req->flags2 & FLAGS2_DFS_PATHNAMES,
newname,
true,
+ !conn->sconn->using_smb2,
&newname,
&dest_has_wcard);
if (!NT_STATUS_IS_OK(status)) {
@@ -6355,8 +6400,8 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
if (fsp) {
DEBUG(10,("smb_file_rename_information: "
- "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
- fsp->fnum, fsp_str_dbg(fsp),
+ "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
+ fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
smb_fname_str_dbg(smb_fname_dst)));
status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
overwrite);
@@ -6584,8 +6629,9 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
return NT_STATUS_INVALID_PARAMETER;
}
- if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
- return NT_STATUS_ACCESS_DENIED;
+ status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
/* Set the attributes */
@@ -6624,6 +6670,7 @@ static NTSTATUS smb_set_info_standard(connection_struct *conn,
files_struct *fsp,
const struct smb_filename *smb_fname)
{
+ NTSTATUS status;
struct smb_file_time ft;
ZERO_STRUCT(ft);
@@ -6632,10 +6679,6 @@ static NTSTATUS smb_set_info_standard(connection_struct *conn,
return NT_STATUS_INVALID_PARAMETER;
}
- if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
- return NT_STATUS_ACCESS_DENIED;
- }
-
/* create time */
ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
/* access time */
@@ -6646,6 +6689,11 @@ static NTSTATUS smb_set_info_standard(connection_struct *conn,
DEBUG(10,("smb_set_info_standard: file %s\n",
smb_fname_str_dbg(smb_fname)));
+ status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
return smb_set_file_time(conn,
fsp,
smb_fname,
@@ -6677,15 +6725,7 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
}
allocation_size = (uint64_t)IVAL(pdata,0);
-#ifdef LARGE_SMB_OFF_T
allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
-#else /* LARGE_SMB_OFF_T */
- if (IVAL(pdata,4) != 0) {
- /* more than 32 bits? */
- return NT_STATUS_INVALID_PARAMETER;
- }
-#endif /* LARGE_SMB_OFF_T */
-
DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
"file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
(double)allocation_size));
@@ -6694,16 +6734,16 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
allocation_size = smb_roundup(conn, allocation_size);
}
- if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
- return NT_STATUS_ACCESS_DENIED;
- }
-
DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
"allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
(double)allocation_size));
if (fsp && fsp->fh->fd != -1) {
/* Open file handle. */
+ if (!(fsp->access_mask & FILE_WRITE_DATA)) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
/* Only change if needed. */
if (allocation_size != get_file_size_stat(&smb_fname->st)) {
if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
@@ -6776,29 +6816,18 @@ static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
const struct smb_filename *smb_fname,
bool fail_after_createfile)
{
- SMB_OFF_T size;
+ off_t size;
if (total_data < 8) {
return NT_STATUS_INVALID_PARAMETER;
}
size = IVAL(pdata,0);
-#ifdef LARGE_SMB_OFF_T
- size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
-#else /* LARGE_SMB_OFF_T */
- if (IVAL(pdata,4) != 0) {
- /* more than 32 bits? */
- return NT_STATUS_INVALID_PARAMETER;
- }
-#endif /* LARGE_SMB_OFF_T */
+ size |= (((off_t)IVAL(pdata,4)) << 32);
DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
"file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
(double)size));
- if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
- return NT_STATUS_ACCESS_DENIED;
- }
-
return smb_set_file_size(conn, req,
fsp,
smb_fname,
@@ -6906,7 +6935,7 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
struct smb_file_time ft;
uint32 raw_unixmode;
mode_t unixmode;
- SMB_OFF_T size = 0;
+ off_t size = 0;
uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
NTSTATUS status = NT_STATUS_OK;
@@ -6927,14 +6956,7 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
size=IVAL(pdata,0); /* first 8 Bytes are size */
-#ifdef LARGE_SMB_OFF_T
- size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
-#else /* LARGE_SMB_OFF_T */
- if (IVAL(pdata,4) != 0) {
- /* more than 32 bits? */
- return NT_STATUS_INVALID_PARAMETER;
- }
-#endif /* LARGE_SMB_OFF_T */
+ size |= (((off_t)IVAL(pdata,4)) << 32);
}
ft.atime = interpret_long_date(pdata+24); /* access_time */
@@ -7380,19 +7402,12 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
/* File exists open. File not exist create. */
create_disp = FILE_OPEN_IF;
break;
- case SMB_O_EXCL:
- /* O_EXCL on its own without O_CREAT is undefined.
- We deliberately ignore it as some versions of
- Linux CIFSFS can send a bare O_EXCL on the
- wire which other filesystems in the kernel
- ignore. See bug 9519 for details. */
-
- /* Fallthrough. */
-
case 0:
/* File exists open. File not exist fail. */
create_disp = FILE_OPEN;
break;
+ case SMB_O_EXCL:
+ /* O_EXCL on its own without O_CREAT is undefined. */
default:
DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
(unsigned int)wire_open_mode ));
@@ -7624,8 +7639,7 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
* non-POSIX opens return SHARING_VIOLATION.
*/
- lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
- NULL);
+ lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
if (lck == NULL) {
DEBUG(0, ("smb_posix_unlink: Could not get share mode "
"lock for file %s\n", fsp_str_dbg(fsp)));
@@ -7638,15 +7652,18 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
* don't delete. If all opens are POSIX delete we can set the delete
* on close disposition.
*/
- for (i=0; i<lck->num_share_modes; i++) {
- struct share_mode_entry *e = &lck->share_modes[i];
+ 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);
+ TALLOC_FREE(lck);
return NT_STATUS_SHARING_VIOLATION;
}
}
@@ -7660,12 +7677,12 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
fsp,
smb_fname);
- TALLOC_FREE(lck);
-
if (!NT_STATUS_IS_OK(status)) {
close_file(req, fsp, NORMAL_CLOSE);
+ TALLOC_FREE(lck);
return status;
}
+ TALLOC_FREE(lck);
return close_file(req, fsp, NORMAL_CLOSE);
}
@@ -7696,9 +7713,10 @@ NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
}
}
- DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
+ DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
"totdata=%d\n", smb_fname_str_dbg(smb_fname),
- fsp ? fsp->fnum : -1, info_level, total_data));
+ fsp_fnum_dbg(fsp),
+ info_level, total_data));
switch (info_level) {
@@ -8051,7 +8069,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
*/
if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
DEBUG(3,("call_trans2setfilepathinfo: fstat "
- "of fnum %d failed (%s)\n", fsp->fnum,
+ "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
strerror(errno)));
reply_nterror(req, map_nt_error_from_unix(errno));
return;
@@ -8119,9 +8137,10 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
}
}
- DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
+ DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
"totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
- fsp ? fsp->fnum : -1, info_level,total_data));
+ fsp_fnum_dbg(fsp),
+ info_level,total_data));
/* Realloc the parameter size */
*pparams = (char *)SMB_REALLOC(*pparams,2);
@@ -8140,7 +8159,7 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
ppdata, total_data,
&data_return_size);
if (!NT_STATUS_IS_OK(status)) {
- if (open_was_deferred(req->mid)) {
+ if (open_was_deferred(req->sconn, req->mid)) {
/* We have re-scheduled this call. */
return;
}
@@ -8421,7 +8440,7 @@ static void call_trans2getdfsreferral(connection_struct *conn,
return;
}
- SSVAL(req->inbuf, smb_flg2,
+ SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
@@ -8464,16 +8483,13 @@ static void call_trans2ioctl(connection_struct *conn,
CAN ACCEPT THIS IN UNICODE. JRA. */
/* Job number */
- if (fsp->print_file) {
- SSVAL(pdata, 0, fsp->print_file->rap_jobid);
- } else {
- SSVAL(pdata, 0, 0);
- }
+ SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
+
srvstr_push(pdata, req->flags2, pdata + 2,
- global_myname(), 15,
+ lp_netbios_name(), 15,
STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
srvstr_push(pdata, req->flags2, pdata+18,
- lp_servicename(SNUM(conn)), 13,
+ lp_servicename(talloc_tos(), SNUM(conn)), 13,
STR_ASCII|STR_TERMINATE); /* Service name */
send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
max_data_bytes);
@@ -8552,12 +8568,12 @@ static void handle_trans2(connection_struct *conn, struct smb_request *req,
{
if (get_Protocol() >= PROTOCOL_NT1) {
req->flags2 |= 0x40; /* IS_LONG_NAME */
- SSVAL(req->inbuf,smb_flg2,req->flags2);
+ SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
}
- if (conn->encrypt_level == Required && !req->encrypted) {
+ if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
if (state->call != TRANSACT2_QFSINFO &&
- state->call != TRANSACT2_SETFSINFO) {
+ state->call != TRANSACT2_SETFSINFO) {
DEBUG(0,("handle_trans2: encryption required "
"with call 0x%x\n",
(unsigned int)state->call));
@@ -8765,7 +8781,7 @@ void reply_trans2(struct smb_request *req)
}
}
- if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
+ if ((state = talloc(conn, struct trans_state)) == NULL) {
DEBUG(0, ("talloc failed\n"));
reply_nterror(req, NT_STATUS_NO_MEMORY);
END_PROFILE(SMBtrans2);
@@ -8911,7 +8927,7 @@ void reply_transs2(struct smb_request *req)
START_PROFILE(SMBtranss2);
- show_msg((char *)req->inbuf);
+ show_msg((const char *)req->inbuf);
/* Windows clients expect all replies to
a transact secondary (SMBtranss2 0x33)