summaryrefslogtreecommitdiffstats
path: root/source/smbd/nttrans.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/smbd/nttrans.c')
-rw-r--r--source/smbd/nttrans.c303
1 files changed, 95 insertions, 208 deletions
diff --git a/source/smbd/nttrans.c b/source/smbd/nttrans.c
index a3ffaad24ac..fbb73640901 100644
--- a/source/smbd/nttrans.c
+++ b/source/smbd/nttrans.c
@@ -21,7 +21,6 @@
#include "includes.h"
-extern int max_send;
extern enum protocol_types Protocol;
extern int smb_read_error;
extern int global_oplock_break;
@@ -41,8 +40,6 @@ static const char *known_nt_pipes[] = {
"\\spoolss",
"\\netdfs",
"\\rpcecho",
- "\\svcctl",
- "\\eventlog",
NULL
};
@@ -84,6 +81,7 @@ static char *nttrans_realloc(char **ptr, size_t size)
static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, NTSTATUS nt_error, char *params,
int paramsize, char *pdata, int datasize)
{
+ extern int max_send;
int data_to_send = datasize;
int params_to_send = paramsize;
int useable_space;
@@ -355,11 +353,6 @@ static int map_share_mode( char *fname, uint32 create_options,
int smb_open_mode = -1;
uint32 original_desired_access = *desired_access;
- /* This is a nasty hack - must fix... JRA. */
- if (*desired_access == MAXIMUM_ALLOWED_ACCESS) {
- *desired_access = FILE_GENERIC_ALL;
- }
-
/*
* Convert GENERIC bits to specific bits.
*/
@@ -588,6 +581,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
uint32 create_disposition = IVAL(inbuf,smb_ntcreate_CreateDisposition);
uint32 create_options = IVAL(inbuf,smb_ntcreate_CreateOptions);
uint16 root_dir_fid = (uint16)IVAL(inbuf,smb_ntcreate_RootDirectoryFid);
+ SMB_BIG_UINT allocation_size = 0;
int smb_ofun;
int smb_open_mode;
/* Breakout the oplock request bits so we can set the
@@ -636,7 +630,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
if((smb_ofun = map_create_disposition( create_disposition )) == -1) {
END_PROFILE(SMBntcreateX);
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ return(ERROR_DOS(ERRDOS,ERRnoaccess));
}
/*
@@ -889,8 +883,10 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
if (create_options & FILE_NON_DIRECTORY_FILE) {
restore_case_semantics(conn, file_attributes);
+ SSVAL(outbuf, smb_flg2,
+ SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
END_PROFILE(SMBntcreateX);
- return ERROR_FORCE_NT(NT_STATUS_FILE_IS_A_DIRECTORY);
+ return ERROR_NT(NT_STATUS_FILE_IS_A_DIRECTORY);
}
oplock_request = 0;
@@ -907,6 +903,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
END_PROFILE(SMBntcreateX);
if (open_was_deferred(SVAL(inbuf,smb_mid))) {
/* We have re-scheduled this call. */
+ clear_cached_errors();
return -1;
}
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
@@ -918,9 +915,8 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
file_len = sbuf.st_size;
fmode = dos_mode(conn,fname,&sbuf);
- if(fmode == 0) {
+ if(fmode == 0)
fmode = FILE_ATTRIBUTE_NORMAL;
- }
if (!fsp->is_directory && (fmode & aDIR)) {
close_file(fsp,False);
END_PROFILE(SMBntcreateX);
@@ -928,27 +924,25 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
}
/* Save the requested allocation size. */
- if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
- SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize);
+ allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize);
#ifdef LARGE_SMB_OFF_T
- allocation_size |= (((SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize + 4)) << 32);
+ allocation_size |= (((SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize + 4)) << 32);
#endif
- if (allocation_size && (allocation_size > (SMB_BIG_UINT)file_len)) {
- fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
- if (fsp->is_directory) {
- close_file(fsp,False);
- END_PROFILE(SMBntcreateX);
- /* Can't set allocation size on a directory. */
- return ERROR_NT(NT_STATUS_ACCESS_DENIED);
- }
- if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
- close_file(fsp,False);
- END_PROFILE(SMBntcreateX);
- return ERROR_NT(NT_STATUS_DISK_FULL);
- }
- } else {
- fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)file_len);
+ if (allocation_size && (allocation_size > (SMB_BIG_UINT)file_len)) {
+ fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
+ if (fsp->is_directory) {
+ close_file(fsp,False);
+ END_PROFILE(SMBntcreateX);
+ /* Can't set allocation size on a directory. */
+ return ERROR_NT(NT_STATUS_ACCESS_DENIED);
}
+ if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
+ close_file(fsp,False);
+ END_PROFILE(SMBntcreateX);
+ return ERROR_NT(NT_STATUS_DISK_FULL);
+ }
+ } else {
+ fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)file_len);
}
/*
@@ -957,13 +951,11 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
* correct bit for extended oplock reply.
*/
- if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
+ if (oplock_request && lp_fake_oplocks(SNUM(conn)))
extended_oplock_granted = True;
- }
- if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
+ if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
extended_oplock_granted = True;
- }
#if 0
/* W2K sends back 42 words here ! If we do the same it breaks offline sync. Go figure... ? JRA. */
@@ -1167,34 +1159,6 @@ static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 secu
}
/****************************************************************************
- Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
-****************************************************************************/
-
-static struct ea_list *read_nttrans_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
-{
- struct ea_list *ea_list_head = NULL;
- size_t offset = 0;
-
- if (data_size < 4) {
- return NULL;
- }
-
- while (offset + 4 <= data_size) {
- size_t next_offset = IVAL(pdata,offset);
- struct ea_list *tmp;
- struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset + 4, data_size - offset - 4, NULL);
-
- DLIST_ADD_END(ea_list_head, eal, tmp);
- if (next_offset == 0) {
- break;
- }
- offset += next_offset;
- }
-
- return ea_list_head;
-}
-
-/****************************************************************************
Reply to a NT_TRANSACT_CREATE call (needs to process SD's).
****************************************************************************/
@@ -1223,14 +1187,11 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
uint32 create_disposition;
uint32 create_options;
uint32 sd_len;
- uint32 ea_len;
uint16 root_dir_fid;
+ SMB_BIG_UINT allocation_size = 0;
int smb_ofun;
int smb_open_mode;
time_t c_time;
- struct ea_list *ea_list = NULL;
- TALLOC_CTX *ctx = NULL;
- char *pdata = NULL;
NTSTATUS status;
DEBUG(5,("call_nt_transact_create\n"));
@@ -1256,7 +1217,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
if(parameter_count < 54) {
DEBUG(0,("call_nt_transact_create - insufficient parameters (%u)\n", (unsigned int)parameter_count));
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ return ERROR_DOS(ERRDOS,ERRnoaccess);
}
flags = IVAL(params,0);
@@ -1266,32 +1227,8 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
create_disposition = IVAL(params,28);
create_options = IVAL(params,32);
sd_len = IVAL(params,36);
- ea_len = IVAL(params,40);
root_dir_fid = (uint16)IVAL(params,4);
- /* Ensure the data_len is correct for the sd and ea values given. */
- if ((ea_len + sd_len > data_count) ||
- (ea_len > data_count) || (sd_len > data_count) ||
- (ea_len + sd_len < ea_len) || (ea_len + sd_len < sd_len)) {
- DEBUG(10,("call_nt_transact_create - ea_len = %u, sd_len = %u, data_count = %u\n",
- (unsigned int)ea_len, (unsigned int)sd_len, (unsigned int)data_count ));
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
- }
-
- if (ea_len) {
- if (!lp_ea_support(SNUM(conn))) {
- DEBUG(10,("call_nt_transact_create - ea_len = %u but EA's not supported.\n",
- (unsigned int)ea_len ));
- return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
- }
-
- if (ea_len < 10) {
- DEBUG(10,("call_nt_transact_create - ea_len = %u - too small (should be more than 10)\n",
- (unsigned int)ea_len ));
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
- }
- }
-
if (create_options & FILE_OPEN_BY_FILE_ID) {
return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
}
@@ -1301,9 +1238,8 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
* NT values, as that's what our code is structured to accept.
*/
- if((smb_ofun = map_create_disposition( create_disposition )) == -1) {
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
- }
+ if((smb_ofun = map_create_disposition( create_disposition )) == -1)
+ return ERROR_DOS(ERRDOS,ERRbadmem);
/*
* Get the file name.
@@ -1425,25 +1361,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
}
}
- if (ea_len) {
- ctx = talloc_init("NTTRANS_CREATE_EA");
- if (!ctx) {
- talloc_destroy(ctx);
- restore_case_semantics(conn, file_attributes);
- return ERROR_NT(NT_STATUS_NO_MEMORY);
- }
-
- pdata = data + sd_len;
-
- /* We have already checked that ea_len <= data_count here. */
- ea_list = read_nttrans_ea_list(ctx, pdata, ea_len);
- if (!ea_list ) {
- talloc_destroy(ctx);
- restore_case_semantics(conn, file_attributes);
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
- }
- }
-
/*
* If it's a request for a directory open, deal with it separately.
*/
@@ -1452,8 +1369,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
/* Can't open a temp directory. IFS kit test. */
if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) {
- talloc_destroy(ctx);
- restore_case_semantics(conn, file_attributes);
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
@@ -1468,7 +1383,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action);
if(!fsp) {
- talloc_destroy(ctx);
restore_case_semantics(conn, file_attributes);
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
}
@@ -1484,6 +1398,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
oplock_request,&rmode,&smb_action);
if (!fsp) {
+
if(errno == EISDIR) {
/*
@@ -1492,113 +1407,84 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
if (create_options & FILE_NON_DIRECTORY_FILE) {
restore_case_semantics(conn, file_attributes);
- return ERROR_FORCE_NT(NT_STATUS_FILE_IS_A_DIRECTORY);
+ SSVAL(outbuf, smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES);
+ return ERROR_NT(NT_STATUS_FILE_IS_A_DIRECTORY);
}
oplock_request = 0;
fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action);
if(!fsp) {
- talloc_destroy(ctx);
restore_case_semantics(conn, file_attributes);
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
}
} else {
- talloc_destroy(ctx);
restore_case_semantics(conn, file_attributes);
if (open_was_deferred(SVAL(inbuf,smb_mid))) {
/* We have re-scheduled this call. */
+ clear_cached_errors();
return -1;
}
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
}
}
- }
-
- /*
- * According to the MS documentation, the only time the security
- * descriptor is applied to the opened file is iff we *created* the
- * file; an existing file stays the same.
- *
- * Also, it seems (from observation) that you can open the file with
- * any access mask but you can still write the sd. We need to override
- * the granted access before we call set_sd
- * Patch for bug #2242 from Tom Lackemann <cessnatomny@yahoo.com>.
- */
-
- if (lp_nt_acl_support(SNUM(conn)) && sd_len && smb_action == FILE_WAS_CREATED) {
- uint32 saved_access = fsp->desired_access;
-
- /* We have already checked that sd_len <= data_count here. */
-
- fsp->desired_access = FILE_GENERIC_ALL;
+
+ file_len = sbuf.st_size;
+ fmode = dos_mode(conn,fname,&sbuf);
+ if(fmode == 0)
+ fmode = FILE_ATTRIBUTE_NORMAL;
- status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION);
- if (!NT_STATUS_IS_OK(status)) {
- talloc_destroy(ctx);
+ if (fmode & aDIR) {
close_file(fsp,False);
restore_case_semantics(conn, file_attributes);
- return ERROR_NT(status);
- }
- fsp->desired_access = saved_access;
- }
-
- if (ea_len && (smb_action == FILE_WAS_CREATED)) {
- status = set_ea(conn, fsp, fname, ea_list);
- talloc_destroy(ctx);
- if (!NT_STATUS_IS_OK(status)) {
- close_file(fsp,False);
- restore_case_semantics(conn, file_attributes);
- return ERROR_NT(status);
- }
+ return ERROR_DOS(ERRDOS,ERRnoaccess);
+ }
+
+ /*
+ * If the caller set the extended oplock request bit
+ * and we granted one (by whatever means) - set the
+ * correct bit for extended oplock reply.
+ */
+
+ if (oplock_request && lp_fake_oplocks(SNUM(conn)))
+ extended_oplock_granted = True;
+
+ if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
+ extended_oplock_granted = True;
}
- restore_case_semantics(conn, file_attributes);
+ /*
+ * Now try and apply the desired SD.
+ */
- file_len = sbuf.st_size;
- fmode = dos_mode(conn,fname,&sbuf);
- if(fmode == 0) {
- fmode = FILE_ATTRIBUTE_NORMAL;
- }
- if (!fsp->is_directory && (fmode & aDIR)) {
+ if (lp_nt_acl_support(SNUM(conn)) && sd_len &&
+ !NT_STATUS_IS_OK(status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION))) {
close_file(fsp,False);
- return ERROR_DOS(ERRDOS,ERRnoaccess);
- }
+ restore_case_semantics(conn, file_attributes);
+ return ERROR_NT(status);
+ }
+ restore_case_semantics(conn, file_attributes);
+
/* Save the requested allocation size. */
- if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
- SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(params,12);
+ allocation_size = (SMB_BIG_UINT)IVAL(params,12);
#ifdef LARGE_SMB_OFF_T
- allocation_size |= (((SMB_BIG_UINT)IVAL(params,16)) << 32);
+ allocation_size |= (((SMB_BIG_UINT)IVAL(params,16)) << 32);
#endif
- if (allocation_size && (allocation_size > file_len)) {
- fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
- if (fsp->is_directory) {
- close_file(fsp,False);
- /* Can't set allocation size on a directory. */
- return ERROR_NT(NT_STATUS_ACCESS_DENIED);
- }
- if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
- close_file(fsp,False);
- return ERROR_NT(NT_STATUS_DISK_FULL);
- }
- } else {
- fsp->initial_allocation_size = smb_roundup(fsp->conn, (SMB_BIG_UINT)file_len);
+ if (allocation_size && (allocation_size > file_len)) {
+ fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
+ if (fsp->is_directory) {
+ close_file(fsp,False);
+ END_PROFILE(SMBntcreateX);
+ /* Can't set allocation size on a directory. */
+ return ERROR_NT(NT_STATUS_ACCESS_DENIED);
}
- }
-
- /*
- * If the caller set the extended oplock request bit
- * and we granted one (by whatever means) - set the
- * correct bit for extended oplock reply.
- */
-
- if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
- extended_oplock_granted = True;
- }
-
- if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
- extended_oplock_granted = True;
+ if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
+ close_file(fsp,False);
+ return ERROR_NT(NT_STATUS_DISK_FULL);
+ }
+ } else {
+ fsp->initial_allocation_size = smb_roundup(fsp->conn, (SMB_BIG_UINT)file_len);
}
/* Realloc the size of parameters and data we will return */
@@ -1776,11 +1662,12 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
&access_mode,&smb_action);
if (!fsp1) {
- get_saved_error_triple(NULL, NULL, &status);
- if (NT_STATUS_IS_OK(status)) {
- status = NT_STATUS_ACCESS_DENIED;
- }
- set_saved_error_triple(0, 0, NT_STATUS_OK);
+ status = NT_STATUS_ACCESS_DENIED;
+ if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
+ status = NT_STATUS_SHARING_VIOLATION;
+ unix_ERR_class = 0;
+ unix_ERR_code = 0;
+ unix_ERR_ntstatus = NT_STATUS_OK;
return status;
}
@@ -1789,11 +1676,12 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
&access_mode,&smb_action);
if (!fsp2) {
- get_saved_error_triple(NULL, NULL, &status);
- if (NT_STATUS_IS_OK(status)) {
- status = NT_STATUS_ACCESS_DENIED;
- }
- set_saved_error_triple(0, 0, NT_STATUS_OK);
+ status = NT_STATUS_ACCESS_DENIED;
+ if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
+ status = NT_STATUS_SHARING_VIOLATION;
+ unix_ERR_class = 0;
+ unix_ERR_code = 0;
+ unix_ERR_ntstatus = NT_STATUS_OK;
close_file(fsp1,False);
return status;
}
@@ -1899,6 +1787,7 @@ int reply_ntrename(connection_struct *conn,
END_PROFILE(SMBntrename);
if (open_was_deferred(SVAL(inbuf,smb_mid))) {
/* We have re-scheduled this call. */
+ clear_cached_errors();
return -1;
}
return ERROR_NT(status);
@@ -2020,6 +1909,7 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o
static size_t get_null_nt_acl(TALLOC_CTX *mem_ctx, SEC_DESC **ppsd)
{
+ extern DOM_SID global_sid_World;
size_t sd_size;
*ppsd = make_standard_sec_desc( mem_ctx, &global_sid_World, &global_sid_World, NULL, &sd_size);
@@ -2946,9 +2836,6 @@ due to being in oplock break state.\n", (unsigned int)function_code ));
ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
- /* We need to re-calcuate the new length after we've read the secondary packet. */
- length = smb_len(inbuf) + 4;
-
/*
* The sequence number for the trans reply is always
* based on the last secondary received.
@@ -2996,7 +2883,7 @@ due to being in oplock break state.\n", (unsigned int)function_code ));
goto bad_param;
if (parameter_displacement > total_parameter_count)
goto bad_param;
- if ((smb_base(inbuf) + parameter_offset + parameter_count > inbuf + length) ||
+ if ((smb_base(inbuf) + parameter_offset + parameter_count >= inbuf + bufsize) ||
(smb_base(inbuf) + parameter_offset + parameter_count < smb_base(inbuf)))
goto bad_param;
if (parameter_displacement + params < params)
@@ -3013,7 +2900,7 @@ due to being in oplock break state.\n", (unsigned int)function_code ));
goto bad_param;
if (data_displacement > total_data_count)
goto bad_param;
- if ((smb_base(inbuf) + data_offset + data_count > inbuf + length) ||
+ if ((smb_base(inbuf) + data_offset + data_count >= inbuf + bufsize) ||
(smb_base(inbuf) + data_offset + data_count < smb_base(inbuf)))
goto bad_param;
if (data_displacement + data < data)