*/
#include "includes.h"
+#include "smbd/globals.h"
-extern int max_send;
extern enum protocol_types Protocol;
-extern struct current_user current_user;
-
-static const char *known_nt_pipes[] = {
- "\\LANMAN",
- "\\srvsvc",
- "\\samr",
- "\\wkssvc",
- "\\NETLOGON",
- "\\ntlsa",
- "\\ntsvcs",
- "\\lsass",
- "\\lsarpc",
- "\\winreg",
- "\\initshutdown",
- "\\spoolss",
- "\\netdfs",
- "\\rpcecho",
- "\\svcctl",
- "\\eventlog",
- "\\unixinfo",
- NULL
-};
+extern const struct generic_mapping file_generic_mapping;
static char *nttrans_realloc(char **ptr, size_t size)
{
+ alignment_offset
+ data_alignment_offset);
- /*
- * useable_space can never be more than max_send minus the
- * alignment offset.
- */
-
- useable_space = MIN(useable_space,
- max_send - (alignment_offset+data_alignment_offset));
-
+ if (useable_space < 0) {
+ char *msg = talloc_asprintf(
+ talloc_tos(),
+ "send_nt_replies failed sanity useable_space = %d!!!",
+ useable_space);
+ DEBUG(0, ("%s\n", msg));
+ exit_server_cleanly(msg);
+ }
while (params_to_send || data_to_send) {
* Calculate whether we will totally or partially fill this packet.
*/
- total_sent_thistime = params_to_send + data_to_send +
- alignment_offset + data_alignment_offset;
+ total_sent_thistime = params_to_send + data_to_send;
/*
* We can never send more than useable_space.
total_sent_thistime = MIN(total_sent_thistime, useable_space);
- reply_outbuf(req, 18, total_sent_thistime);
+ reply_outbuf(req, 18,
+ total_sent_thistime + alignment_offset
+ + data_alignment_offset);
+
+ /*
+ * We might have had SMBnttranss in req->inbuf, fix that.
+ */
+ SCVAL(req->outbuf, smb_com, SMBnttrans);
/*
* Set total params and data to be sent.
if(params_to_send < 0 || data_to_send < 0) {
DEBUG(0,("send_nt_replies failed sanity check pts = %d, dts = %d\n!!!",
params_to_send, data_to_send));
- return;
+ exit_server_cleanly("send_nt_replies: internal error");
}
}
}
An NTFS file name is <path>.<extention>:<stream name>:<stream type>
$DATA can be used as both a stream name and a stream type. A missing stream
name or type implies $DATA.
+
+ Both Windows stream names and POSIX files can contain the ':' character.
+ This function first checks for the existence of a colon in the last component
+ of the given name. If the name contains a colon we differentiate between a
+ stream and POSIX file by checking if the latter exists through a POSIX stat.
+
+ Function assumes we've already chdir() to the "root" directory of fname.
****************************************************************************/
bool is_ntfs_stream_name(const char *fname)
{
+ const char *lastcomp;
+ SMB_STRUCT_STAT sbuf;
+
+ /* If all pathnames are treated as POSIX we ignore streams. */
if (lp_posix_pathnames()) {
- return False;
+ return false;
}
- return (strchr_m(fname, ':') != NULL) ? True : False;
+
+ /* Find the last component of the name. */
+ if ((lastcomp = strrchr_m(fname, '/')) != NULL)
+ ++lastcomp;
+ else
+ lastcomp = fname;
+
+ /* If there is no colon in the last component, it's not a stream. */
+ if (strchr_m(lastcomp, ':') == NULL)
+ return false;
+
+ /*
+ * If file already exists on disk, it's not a stream. The stat must
+ * bypass the vfs layer so streams modules don't intefere.
+ */
+ if (sys_stat(fname, &sbuf) == 0) {
+ DEBUG(5, ("is_ntfs_stream_name: file %s contains a ':' but is "
+ "not a stream\n", fname));
+ return false;
+ }
+
+ return true;
}
/****************************************************************************
static void nt_open_pipe(char *fname, connection_struct *conn,
struct smb_request *req, int *ppnum)
{
- smb_np_struct *p = NULL;
- int i;
+ files_struct *fsp;
+ NTSTATUS status;
DEBUG(4,("nt_open_pipe: Opening pipe %s.\n", fname));
- /* See if it is one we want to handle. */
-
- if (lp_disable_spoolss() && strequal(fname, "\\spoolss")) {
- reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
- ERRDOS, ERRbadpipe);
- return;
- }
-
- for( i = 0; known_nt_pipes[i]; i++ ) {
- if( strequal(fname,known_nt_pipes[i])) {
- break;
- }
- }
-
- if ( known_nt_pipes[i] == NULL ) {
- reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
- ERRDOS, ERRbadpipe);
- return;
- }
-
/* Strip \\ off the name. */
fname++;
- DEBUG(3,("nt_open_pipe: Known pipe %s opening.\n", fname));
-
- p = open_rpc_pipe_p(fname, conn, req->vuid);
- if (!p) {
- reply_doserror(req, ERRSRV, ERRnofids);
+ status = open_np_file(req, fname, &fsp);
+ if (!NT_STATUS_IS_OK(status)) {
+ if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+ reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
+ ERRDOS, ERRbadpipe);
+ return;
+ }
+ reply_nterror(req, status);
return;
}
- /* TODO: Add pipe to db */
-
- if ( !store_pipe_opendb( p ) ) {
- DEBUG(3,("nt_open_pipe: failed to store %s pipe open.\n", fname));
- }
-
- *ppnum = p->pnum;
+ *ppnum = fsp->fnum;
return;
}
char *fname = NULL;
int pnum = -1;
char *p = NULL;
- uint32 flags = IVAL(req->inbuf,smb_ntcreate_Flags);
+ uint32 flags = IVAL(req->vwv+3, 1);
TALLOC_CTX *ctx = talloc_tos();
- srvstr_pull_buf_talloc(ctx, (char *)req->inbuf, req->flags2, &fname,
- smb_buf(req->inbuf), STR_TERMINATE);
+ srvstr_pull_req_talloc(ctx, req, &fname, req->buf, STR_TERMINATE);
if (!fname) {
reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
uint32 create_disposition;
uint32 create_options;
uint16 root_dir_fid;
- SMB_BIG_UINT allocation_size;
+ uint64_t allocation_size;
/* Breakout the oplock request bits so we can set the
reply bits separately. */
uint32 fattr=0;
return;
}
- flags = IVAL(req->inbuf,smb_ntcreate_Flags);
- access_mask = IVAL(req->inbuf,smb_ntcreate_DesiredAccess);
- file_attributes = IVAL(req->inbuf,smb_ntcreate_FileAttributes);
- share_access = IVAL(req->inbuf,smb_ntcreate_ShareAccess);
- create_disposition = IVAL(req->inbuf,smb_ntcreate_CreateDisposition);
- create_options = IVAL(req->inbuf,smb_ntcreate_CreateOptions);
- root_dir_fid = (uint16)IVAL(req->inbuf,smb_ntcreate_RootDirectoryFid);
+ flags = IVAL(req->vwv+3, 1);
+ access_mask = IVAL(req->vwv+7, 1);
+ file_attributes = IVAL(req->vwv+13, 1);
+ share_access = IVAL(req->vwv+15, 1);
+ create_disposition = IVAL(req->vwv+17, 1);
+ create_options = IVAL(req->vwv+19, 1);
+ root_dir_fid = (uint16)IVAL(req->vwv+5, 1);
- allocation_size = (SMB_BIG_UINT)IVAL(req->inbuf,
- smb_ntcreate_AllocationSize);
+ allocation_size = (uint64_t)IVAL(req->vwv+9, 1);
#ifdef LARGE_SMB_OFF_T
- allocation_size |= (((SMB_BIG_UINT)IVAL(
- req->inbuf,
- smb_ntcreate_AllocationSize + 4)) << 32);
+ allocation_size |= (((uint64_t)IVAL(req->vwv+11, 1)) << 32);
#endif
- srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname,
- smb_buf(req->inbuf), 0, STR_TERMINATE, &status);
+ srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
+ STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
(unsigned int)root_dir_fid,
fname));
+ /*
+ * we need to remove ignored bits when they come directly from the client
+ * because we reuse some of them for internal stuff
+ */
+ create_options &= ~NTCREATEX_OPTIONS_MUST_IGNORE_MASK;
+
/*
* If it's an IPC, use the pipe handler.
*/
? BATCH_OPLOCK : 0;
}
- status = create_file(conn, req, root_dir_fid, fname,
- access_mask, share_access, create_disposition,
- create_options, file_attributes, oplock_request,
- allocation_size, NULL, NULL, &fsp, &info, &sbuf);
+ status = SMB_VFS_CREATE_FILE(
+ conn, /* conn */
+ req, /* req */
+ root_dir_fid, /* root_dir_fid */
+ fname, /* fname */
+ CFF_DOS_PATH, /* create_file_flags */
+ access_mask, /* access_mask */
+ share_access, /* share_access */
+ create_disposition, /* create_disposition*/
+ create_options, /* create_options */
+ file_attributes, /* file_attributes */
+ oplock_request, /* oplock_request */
+ allocation_size, /* allocation_size */
+ NULL, /* sd */
+ NULL, /* ea_list */
+ &fsp, /* result */
+ &info, /* pinfo */
+ &sbuf); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
if (open_was_deferred(req->mid)) {
return status;
}
- if (psd->owner_sid==0) {
+ if (psd->owner_sid == NULL) {
security_info_sent &= ~OWNER_SECURITY_INFORMATION;
}
- if (psd->group_sid==0) {
+ if (psd->group_sid == NULL) {
security_info_sent &= ~GROUP_SECURITY_INFORMATION;
}
- if (psd->sacl==0) {
- security_info_sent &= ~SACL_SECURITY_INFORMATION;
- }
- if (psd->dacl==0) {
- security_info_sent &= ~DACL_SECURITY_INFORMATION;
+
+ /* Convert all the generic bits. */
+ security_acl_map_generic(psd->dacl, &file_generic_mapping);
+ security_acl_map_generic(psd->sacl, &file_generic_mapping);
+
+ if (DEBUGLEVEL >= 10) {
+ DEBUG(10,("set_sd for file %s\n", fsp->fsp_name ));
+ NDR_PRINT_DEBUG(security_descriptor, psd);
}
status = SMB_VFS_FSET_NT_ACL(fsp, security_info_sent, psd);
struct ea_list *ea_list = NULL;
NTSTATUS status;
size_t param_len;
- SMB_BIG_UINT allocation_size;
+ uint64_t allocation_size;
int oplock_request;
uint8_t oplock_granted;
TALLOC_CTX *ctx = talloc_tos();
sd_len = IVAL(params,36);
ea_len = IVAL(params,40);
root_dir_fid = (uint16)IVAL(params,4);
- allocation_size = (SMB_BIG_UINT)IVAL(params,12);
+ allocation_size = (uint64_t)IVAL(params,12);
#ifdef LARGE_SMB_OFF_T
- allocation_size |= (((SMB_BIG_UINT)IVAL(params,16)) << 32);
+ allocation_size |= (((uint64_t)IVAL(params,16)) << 32);
#endif
+ /*
+ * we need to remove ignored bits when they come directly from the client
+ * because we reuse some of them for internal stuff
+ */
+ create_options &= ~NTCREATEX_OPTIONS_MUST_IGNORE_MASK;
+
/* 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)
? BATCH_OPLOCK : 0;
}
- status = create_file(conn, req, root_dir_fid, fname,
- access_mask, share_access, create_disposition,
- create_options, file_attributes, oplock_request,
- allocation_size, sd, ea_list, &fsp, &info, &sbuf);
+ status = SMB_VFS_CREATE_FILE(
+ conn, /* conn */
+ req, /* req */
+ root_dir_fid, /* root_dir_fid */
+ fname, /* fname */
+ CFF_DOS_PATH, /* create_file_flags */
+ access_mask, /* access_mask */
+ share_access, /* share_access */
+ create_disposition, /* create_disposition*/
+ create_options, /* create_options */
+ file_attributes, /* file_attributes */
+ oplock_request, /* oplock_request */
+ allocation_size, /* allocation_size */
+ sd, /* sd */
+ ea_list, /* ea_list */
+ &fsp, /* result */
+ &info, /* pinfo */
+ &sbuf); /* psbuf */
if(!NT_STATUS_IS_OK(status)) {
if (open_was_deferred(req->mid)) {
int info;
SMB_OFF_T ret=-1;
NTSTATUS status = NT_STATUS_OK;
+ char *parent;
ZERO_STRUCT(sbuf1);
ZERO_STRUCT(sbuf2);
DEBUG(10,("copy_internals: doing file copy %s to %s\n",
oldname, newname));
- status = open_file_ntcreate(conn, req, oldname, &sbuf1,
- FILE_READ_DATA, /* Read-only. */
- FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
- FILE_OPEN,
- 0, /* No create options. */
- FILE_ATTRIBUTE_NORMAL,
- NO_OPLOCK,
- &info, &fsp1);
+ status = SMB_VFS_CREATE_FILE(
+ conn, /* conn */
+ req, /* req */
+ 0, /* root_dir_fid */
+ oldname, /* fname */
+ 0, /* create_file_flags */
+ FILE_READ_DATA, /* access_mask */
+ (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
+ FILE_SHARE_DELETE),
+ FILE_OPEN, /* create_disposition*/
+ 0, /* create_options */
+ FILE_ATTRIBUTE_NORMAL, /* file_attributes */
+ NO_OPLOCK, /* oplock_request */
+ 0, /* allocation_size */
+ NULL, /* sd */
+ NULL, /* ea_list */
+ &fsp1, /* result */
+ &info, /* pinfo */
+ &sbuf1); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- status = open_file_ntcreate(conn, req, newname, &sbuf2,
- FILE_WRITE_DATA, /* Read-only. */
- FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
- FILE_CREATE,
- 0, /* No create options. */
- fattr,
- NO_OPLOCK,
- &info, &fsp2);
+ status = SMB_VFS_CREATE_FILE(
+ conn, /* conn */
+ req, /* req */
+ 0, /* root_dir_fid */
+ newname, /* fname */
+ 0, /* create_file_flags */
+ FILE_WRITE_DATA, /* access_mask */
+ (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
+ FILE_SHARE_DELETE),
+ FILE_CREATE, /* create_disposition*/
+ 0, /* create_options */
+ fattr, /* file_attributes */
+ NO_OPLOCK, /* oplock_request */
+ 0, /* allocation_size */
+ NULL, /* sd */
+ NULL, /* ea_list */
+ &fsp2, /* result */
+ &info, /* pinfo */
+ &sbuf2); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
- close_file(fsp1,ERROR_CLOSE);
+ close_file(NULL, fsp1, ERROR_CLOSE);
return status;
}
* Thus we don't look at the error return from the
* close of fsp1.
*/
- close_file(fsp1,NORMAL_CLOSE);
+ close_file(NULL, fsp1, NORMAL_CLOSE);
/* Ensure the modtime is set correctly on the destination file. */
set_close_write_time(fsp2, get_mtimespec(&sbuf1));
- status = close_file(fsp2,NORMAL_CLOSE);
+ status = close_file(NULL, fsp2, NORMAL_CLOSE);
/* Grrr. We have to do this as open_file_ntcreate adds aARCH when it
creates the file. This isn't the correct thing to do in the copy
case. JRA */
- file_set_dosmode(conn, newname, fattr, &sbuf2,
- parent_dirname(newname),false);
+ if (!parent_dirname(talloc_tos(), newname, &parent, NULL)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ file_set_dosmode(conn, newname, fattr, &sbuf2, parent, false);
+ TALLOC_FREE(parent);
if (ret < (SMB_OFF_T)sbuf1.st_size) {
return NT_STATUS_DISK_FULL;
connection_struct *conn = req->conn;
char *oldname = NULL;
char *newname = NULL;
- char *p;
+ const char *p;
NTSTATUS status;
bool src_has_wcard = False;
bool dest_has_wcard = False;
return;
}
- attrs = SVAL(req->inbuf,smb_vwv0);
- rename_type = SVAL(req->inbuf,smb_vwv1);
+ attrs = SVAL(req->vwv+0, 0);
+ rename_type = SVAL(req->vwv+1, 0);
- p = smb_buf(req->inbuf) + 1;
- p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &oldname, p,
- 0, STR_TERMINATE, &status,
- &src_has_wcard);
+ p = (const char *)req->buf + 1;
+ p += srvstr_get_path_req_wcard(ctx, req, &oldname, p, STR_TERMINATE,
+ &status, &src_has_wcard);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
END_PROFILE(SMBntrename);
return;
}
- if( is_ntfs_stream_name(oldname)) {
- /* Can't rename a stream. */
- reply_nterror(req, NT_STATUS_ACCESS_DENIED);
- END_PROFILE(SMBntrename);
- return;
- }
-
if (ms_has_wild(oldname)) {
reply_nterror(req, NT_STATUS_OBJECT_PATH_SYNTAX_BAD);
END_PROFILE(SMBntrename);
}
p++;
- p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &newname, p,
- 0, STR_TERMINATE, &status,
- &dest_has_wcard);
+ p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
+ &status, &dest_has_wcard);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
END_PROFILE(SMBntrename);
return;
}
+ /* The new name must begin with a ':' if the old name is a stream. */
+ if (is_ntfs_stream_name(oldname) && (newname[0] != ':')) {
+ reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ END_PROFILE(SMBntrename);
+ return;
+ }
+
DEBUG(3,("reply_ntrename : %s -> %s\n",oldname,newname));
switch(rename_type) {
return;
}
- fsp = file_fsp(SVAL(setup,4));
+ fsp = file_fsp(req, SVAL(setup,4));
filter = IVAL(setup, 0);
recursive = (SVAL(setup, 6) != 0) ? True : False;
* here.
*/
- change_notify_reply(fsp->conn, req->inbuf, max_param_count, fsp->notify);
+ change_notify_reply(fsp->conn, req, max_param_count,
+ fsp->notify);
/*
* change_notify_reply() above has independently sent its
return;
}
- fsp = file_fsp(SVAL(params, 0));
+ fsp = file_fsp(req, SVAL(params, 0));
if (!check_fsp(conn, req, fsp)) {
return;
}
return;
}
- fsp = file_fsp(SVAL(params,0));
+ fsp = file_fsp(req, SVAL(params,0));
if(!fsp) {
reply_doserror(req, ERRDOS, ERRbadfid);
return;
status = SMB_VFS_FGET_NT_ACL(
fsp, security_info_wanted, &psd);
}
-
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
return;
}
- sd_size = ndr_size_security_descriptor(psd, 0);
+ /* If the SACL/DACL is NULL, but was requested, we mark that it is
+ * present in the reply to match Windows behavior */
+ if (psd->sacl == NULL &&
+ security_info_wanted & SACL_SECURITY_INFORMATION)
+ psd->type |= SEC_DESC_SACL_PRESENT;
+ if (psd->dacl == NULL &&
+ security_info_wanted & DACL_SECURITY_INFORMATION)
+ psd->type |= SEC_DESC_DACL_PRESENT;
+
+ sd_size = ndr_size_security_descriptor(psd, NULL, 0);
DEBUG(3,("call_nt_transact_query_security_desc: sd_size = %lu.\n",(unsigned long)sd_size));
+ if (DEBUGLEVEL >= 10) {
+ DEBUG(10,("call_nt_transact_query_security_desc for file %s\n", fsp->fsp_name));
+ NDR_PRINT_DEBUG(security_descriptor, psd);
+ }
+
SIVAL(params,0,(uint32)sd_size);
if (max_data_count < sd_size) {
return;
}
- if((fsp = file_fsp(SVAL(params,0))) == NULL) {
+ if((fsp = file_fsp(req, SVAL(params,0))) == NULL) {
reply_doserror(req, ERRDOS, ERRbadfid);
return;
}
files_struct *fsp;
uint8 isFSctl;
uint8 compfilter;
- static bool logged_message;
char *pdata = *ppdata;
if (setup_count != 8) {
DEBUG(10,("call_nt_transact_ioctl: function[0x%08X] FID[0x%04X] isFSctl[0x%02X] compfilter[0x%02X]\n",
function, fidnum, isFSctl, compfilter));
- fsp=file_fsp(fidnum);
+ fsp=file_fsp(req, fidnum);
/* this check is done in each implemented function case for now
because I don't want to break anything... --metze
FSP_BELONGS_CONN(fsp,conn);*/
return;
}
default:
- if (!logged_message) {
- logged_message = True; /* Only print this once... */
+ if (!logged_ioctl_message) {
+ logged_ioctl_message = true; /* Only print this once... */
DEBUG(0,("call_nt_transact_ioctl(0x%x): Currently not implemented.\n",
function));
}
ZERO_STRUCT(qt);
/* access check */
- if (current_user.ut.uid != 0) {
+ if (conn->server_info->utok.uid != 0) {
DEBUG(1,("get_user_quota: access_denied service [%s] user "
"[%s]\n", lp_servicename(SNUM(conn)),
conn->server_info->unix_name));
}
/* maybe we can check the quota_fnum */
- fsp = file_fsp(SVAL(params,0));
+ fsp = file_fsp(req, SVAL(params,0));
if (!check_fsp_ntquota_handle(conn, req, fsp)) {
DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
reply_nterror(req, NT_STATUS_INVALID_HANDLE);
tmp_list=tmp_list->next,entry+=entry_len,qt_len+=entry_len) {
sid_len = ndr_size_dom_sid(
- &tmp_list->quotas->sid, 0);
+ &tmp_list->quotas->sid, NULL, 0);
entry_len = 40 + sid_len;
/* nextoffset entry 4 bytes */
/* then the len of the SID 4 bytes */
SIVAL(entry,4,sid_len);
- /* unknown data 8 bytes SMB_BIG_UINT */
- SBIG_UINT(entry,8,(SMB_BIG_UINT)0); /* this is not 0 in windows...-metze*/
+ /* unknown data 8 bytes uint64_t */
+ SBIG_UINT(entry,8,(uint64_t)0); /* this is not 0 in windows...-metze*/
- /* the used disk space 8 bytes SMB_BIG_UINT */
+ /* the used disk space 8 bytes uint64_t */
SBIG_UINT(entry,16,tmp_list->quotas->usedspace);
- /* the soft quotas 8 bytes SMB_BIG_UINT */
+ /* the soft quotas 8 bytes uint64_t */
SBIG_UINT(entry,24,tmp_list->quotas->softlim);
- /* the hard quotas 8 bytes SMB_BIG_UINT */
+ /* the hard quotas 8 bytes uint64_t */
SBIG_UINT(entry,32,tmp_list->quotas->hardlim);
/* and now the SID */
/* then the len of the SID 4 bytes */
SIVAL(entry,4,sid_len);
- /* unknown data 8 bytes SMB_BIG_UINT */
- SBIG_UINT(entry,8,(SMB_BIG_UINT)0); /* this is not 0 in windows...-mezte*/
+ /* unknown data 8 bytes uint64_t */
+ SBIG_UINT(entry,8,(uint64_t)0); /* this is not 0 in windows...-mezte*/
- /* the used disk space 8 bytes SMB_BIG_UINT */
+ /* the used disk space 8 bytes uint64_t */
SBIG_UINT(entry,16,qt.usedspace);
- /* the soft quotas 8 bytes SMB_BIG_UINT */
+ /* the soft quotas 8 bytes uint64_t */
SBIG_UINT(entry,24,qt.softlim);
- /* the hard quotas 8 bytes SMB_BIG_UINT */
+ /* the hard quotas 8 bytes uint64_t */
SBIG_UINT(entry,32,qt.hardlim);
/* and now the SID */
ZERO_STRUCT(qt);
/* access check */
- if (current_user.ut.uid != 0) {
+ if (conn->server_info->utok.uid != 0) {
DEBUG(1,("set_user_quota: access_denied service [%s] user "
"[%s]\n", lp_servicename(SNUM(conn)),
conn->server_info->unix_name));
}
/* maybe we can check the quota_fnum */
- fsp = file_fsp(SVAL(params,0));
+ fsp = file_fsp(req, SVAL(params,0));
if (!check_fsp_ntquota_handle(conn, req, fsp)) {
DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
reply_nterror(req, NT_STATUS_INVALID_HANDLE);
* maybe its the change time in NTTIME
*/
- /* the used space 8 bytes (SMB_BIG_UINT)*/
- qt.usedspace = (SMB_BIG_UINT)IVAL(pdata,16);
+ /* the used space 8 bytes (uint64_t)*/
+ qt.usedspace = (uint64_t)IVAL(pdata,16);
#ifdef LARGE_SMB_OFF_T
- qt.usedspace |= (((SMB_BIG_UINT)IVAL(pdata,20)) << 32);
+ qt.usedspace |= (((uint64_t)IVAL(pdata,20)) << 32);
#else /* LARGE_SMB_OFF_T */
if ((IVAL(pdata,20) != 0)&&
((qt.usedspace != 0xFFFFFFFF)||
}
#endif /* LARGE_SMB_OFF_T */
- /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
- qt.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
+ /* the soft quotas 8 bytes (uint64_t)*/
+ qt.softlim = (uint64_t)IVAL(pdata,24);
#ifdef LARGE_SMB_OFF_T
- qt.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
+ qt.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
#else /* LARGE_SMB_OFF_T */
if ((IVAL(pdata,28) != 0)&&
((qt.softlim != 0xFFFFFFFF)||
}
#endif /* LARGE_SMB_OFF_T */
- /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
- qt.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
+ /* the hard quotas 8 bytes (uint64_t)*/
+ qt.hardlim = (uint64_t)IVAL(pdata,32);
#ifdef LARGE_SMB_OFF_T
- qt.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
+ qt.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
#else /* LARGE_SMB_OFF_T */
if ((IVAL(pdata,36) != 0)&&
((qt.hardlim != 0xFFFFFFFF)||
uint16 function_code;
NTSTATUS result;
struct trans_state *state;
- uint32_t size;
- uint32_t av_size;
START_PROFILE(SMBnttrans);
return;
}
- size = smb_len(req->inbuf) + 4;
- av_size = smb_len(req->inbuf);
- pscnt = IVAL(req->inbuf,smb_nt_ParameterCount);
- psoff = IVAL(req->inbuf,smb_nt_ParameterOffset);
- dscnt = IVAL(req->inbuf,smb_nt_DataCount);
- dsoff = IVAL(req->inbuf,smb_nt_DataOffset);
- function_code = SVAL(req->inbuf, smb_nt_Function);
+ pscnt = IVAL(req->vwv+9, 1);
+ psoff = IVAL(req->vwv+11, 1);
+ dscnt = IVAL(req->vwv+13, 1);
+ dsoff = IVAL(req->vwv+15, 1);
+ function_code = SVAL(req->vwv+18, 0);
if (IS_IPC(conn) && (function_code != NT_TRANSACT_CREATE)) {
reply_doserror(req, ERRSRV, ERRaccess);
state->mid = req->mid;
state->vuid = req->vuid;
- state->total_data = IVAL(req->inbuf, smb_nt_TotalDataCount);
+ state->total_data = IVAL(req->vwv+3, 1);
state->data = NULL;
- state->total_param = IVAL(req->inbuf, smb_nt_TotalParameterCount);
+ state->total_param = IVAL(req->vwv+1, 1);
state->param = NULL;
- state->max_data_return = IVAL(req->inbuf,smb_nt_MaxDataCount);
- state->max_param_return = IVAL(req->inbuf,smb_nt_MaxParameterCount);
+ state->max_data_return = IVAL(req->vwv+7, 1);
+ state->max_param_return = IVAL(req->vwv+5, 1);
/* setup count is in *words* */
- state->setup_count = 2*CVAL(req->inbuf,smb_nt_SetupCount);
+ state->setup_count = 2*CVAL(req->vwv+17, 1);
state->setup = NULL;
state->call = function_code;
+ DEBUG(10, ("num_setup=%u, "
+ "param_total=%u, this_param=%u, max_param=%u, "
+ "data_total=%u, this_data=%u, max_data=%u, "
+ "param_offset=%u, data_offset=%u\n",
+ (unsigned)state->setup_count,
+ (unsigned)state->total_param, (unsigned)pscnt,
+ (unsigned)state->max_param_return,
+ (unsigned)state->total_data, (unsigned)dscnt,
+ (unsigned)state->max_data_return,
+ (unsigned)psoff, (unsigned)dsoff));
+
/*
* All nttrans messages we handle have smb_wct == 19 +
* state->setup_count. Ensure this is so as a sanity check.
goto bad_param;
if (state->total_data) {
+
+ if (trans_oob(state->total_data, 0, dscnt)
+ || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
+ goto bad_param;
+ }
+
/* Can't use talloc here, the core routines do realloc on the
* params and data. */
if ((state->data = (char *)SMB_MALLOC(state->total_data)) == NULL) {
return;
}
- if (dscnt > state->total_data ||
- dsoff+dscnt < dsoff) {
- goto bad_param;
- }
-
- if (dsoff > av_size ||
- dscnt > av_size ||
- dsoff+dscnt > av_size) {
- goto bad_param;
- }
-
memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
}
if (state->total_param) {
+
+ if (trans_oob(state->total_param, 0, pscnt)
+ || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
+ goto bad_param;
+ }
+
/* Can't use talloc here, the core routines do realloc on the
* params and data. */
if ((state->param = (char *)SMB_MALLOC(state->total_param)) == NULL) {
return;
}
- if (pscnt > state->total_param ||
- psoff+pscnt < psoff) {
- goto bad_param;
- }
-
- if (psoff > av_size ||
- pscnt > av_size ||
- psoff+pscnt > av_size) {
- goto bad_param;
- }
-
memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
}
if(state->setup_count > 0) {
DEBUG(10,("reply_nttrans: state->setup_count = %d\n",
state->setup_count));
+
+ /*
+ * No overflow possible here, state->setup_count is an
+ * unsigned int, being filled by a single byte from
+ * CVAL(req->vwv+13, 0) above. The cast in the comparison
+ * below is not necessary, it's here to clarify things. The
+ * validity of req->vwv and req->wct has been checked in
+ * init_smb_request already.
+ */
+ if ((state->setup_count/2) + 19 > (unsigned int)req->wct) {
+ goto bad_param;
+ }
+
state->setup = (uint16 *)TALLOC(state, state->setup_count);
if (state->setup == NULL) {
DEBUG(0,("reply_nttrans : Out of memory\n"));
return;
}
- if ((smb_nt_SetupStart + state->setup_count < smb_nt_SetupStart) ||
- (smb_nt_SetupStart + state->setup_count < state->setup_count)) {
- goto bad_param;
- }
- if (smb_nt_SetupStart + state->setup_count > size) {
- goto bad_param;
- }
-
- memcpy( state->setup, &req->inbuf[smb_nt_SetupStart],
- state->setup_count);
+ memcpy(state->setup, req->vwv+19, state->setup_count);
dump_data(10, (uint8 *)state->setup, state->setup_count);
}
connection_struct *conn = req->conn;
uint32_t pcnt,poff,dcnt,doff,pdisp,ddisp;
struct trans_state *state;
- uint32_t av_size;
- uint32_t size;
START_PROFILE(SMBnttranss);
/* Revise state->total_param and state->total_data in case they have
changed downwards */
- if (IVAL(req->inbuf, smb_nts_TotalParameterCount)
- < state->total_param) {
- state->total_param = IVAL(req->inbuf,
- smb_nts_TotalParameterCount);
+ if (IVAL(req->vwv+1, 1) < state->total_param) {
+ state->total_param = IVAL(req->vwv+1, 1);
}
- if (IVAL(req->inbuf, smb_nts_TotalDataCount) < state->total_data) {
- state->total_data = IVAL(req->inbuf, smb_nts_TotalDataCount);
+ if (IVAL(req->vwv+3, 1) < state->total_data) {
+ state->total_data = IVAL(req->vwv+3, 1);
}
- size = smb_len(req->inbuf) + 4;
- av_size = smb_len(req->inbuf);
+ pcnt = IVAL(req->vwv+5, 1);
+ poff = IVAL(req->vwv+7, 1);
+ pdisp = IVAL(req->vwv+9, 1);
- pcnt = IVAL(req->inbuf,smb_nts_ParameterCount);
- poff = IVAL(req->inbuf, smb_nts_ParameterOffset);
- pdisp = IVAL(req->inbuf, smb_nts_ParameterDisplacement);
-
- dcnt = IVAL(req->inbuf, smb_nts_DataCount);
- ddisp = IVAL(req->inbuf, smb_nts_DataDisplacement);
- doff = IVAL(req->inbuf, smb_nts_DataOffset);
+ dcnt = IVAL(req->vwv+11, 1);
+ doff = IVAL(req->vwv+13, 1);
+ ddisp = IVAL(req->vwv+15, 1);
state->received_param += pcnt;
state->received_data += dcnt;
goto bad_param;
if (pcnt) {
- if (pdisp > state->total_param ||
- pcnt > state->total_param ||
- pdisp+pcnt > state->total_param ||
- pdisp+pcnt < pdisp) {
+ if (trans_oob(state->total_param, pdisp, pcnt)
+ || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
goto bad_param;
}
-
- if (poff > av_size ||
- pcnt > av_size ||
- poff+pcnt > av_size ||
- poff+pcnt < poff) {
- goto bad_param;
- }
-
- memcpy(state->param+pdisp, smb_base(req->inbuf)+poff,
- pcnt);
+ memcpy(state->param+pdisp, smb_base(req->inbuf)+poff,pcnt);
}
if (dcnt) {
- if (ddisp > state->total_data ||
- dcnt > state->total_data ||
- ddisp+dcnt > state->total_data ||
- ddisp+dcnt < ddisp) {
+ if (trans_oob(state->total_data, ddisp, dcnt)
+ || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
goto bad_param;
}
-
- if (ddisp > av_size ||
- dcnt > av_size ||
- ddisp+dcnt > av_size ||
- ddisp+dcnt < ddisp) {
- goto bad_param;
- }
-
- memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
- dcnt);
+ memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
}
if ((state->received_param < state->total_param) ||
return;
}
- /*
- * construct_reply_common will copy smb_com from inbuf to
- * outbuf. SMBnttranss is wrong here.
- */
- SCVAL(req->inbuf,smb_com,SMBnttrans);
-
handle_nttrans(conn, state, req);
DLIST_REMOVE(conn->pending_trans, state);