extern struct current_user current_user;
#define get_file_size(sbuf) ((sbuf).st_size)
+#define DIR_ENTRY_SAFETY_MARGIN 4096
+
+/********************************************************************
+ Roundup a value to the nearest SMB_ROUNDUP_ALLOCATION_SIZE boundary.
+ Only do this for Windows clients.
+********************************************************************/
+
+SMB_BIG_UINT smb_roundup(SMB_BIG_UINT val)
+{
+ /* Only roundup for Windows clients. */
+ enum remote_arch_types ra_type = get_remote_arch();
+ if ((ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
+ val = SMB_ROUNDUP(val,SMB_ROUNDUP_ALLOCATION_SIZE);
+ }
+ return val;
+}
+
+/********************************************************************
+ Given a stat buffer return the allocated size on disk, taking into
+ account sparse files.
+********************************************************************/
-/* given a stat buffer return the allocated size on disk, taking into
- account sparse files */
SMB_BIG_UINT get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf)
{
SMB_BIG_UINT ret;
+
#if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
#else
ret = (SMB_BIG_UINT)get_file_size(*sbuf);
#endif
+
if (!ret && fsp && fsp->initial_allocation_size)
ret = fsp->initial_allocation_size;
- ret = SMB_ROUNDUP(ret,SMB_ROUNDUP_ALLOCATION_SIZE);
+
+ ret = smb_roundup(ret);
+
return ret;
}
****************************************************************************/
static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
- char **pparams, int total_params, char **ppdata, int total_data)
+ char **pparams, int total_params, char **ppdata, int total_data,
+ unsigned int max_data_bytes)
{
char *params = *pparams;
int16 open_mode;
if (IS_IPC(conn))
return(ERROR_DOS(ERRSRV,ERRaccess));
- srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status, False);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
/* XXXX we need to handle passed times, sattr and flags */
unix_convert(fname,conn,0,&bad_path,&sbuf);
+ if (bad_path) {
+ return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ }
if (!check_name(fname,conn)) {
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
oplock_request, &rmode,&smb_action);
if (!fsp) {
+ 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);
}
return UNIX_TYPE_UNKNOWN;
}
-/****************************************************************************
- Return the major devicenumber for UNIX extensions.
-****************************************************************************/
-
-static uint32 unix_dev_major(SMB_DEV_T dev)
-{
-#if defined(HAVE_DEVICE_MAJOR_FN)
- return (uint32)major(dev);
-#else
- return (uint32)(dev >> 8);
-#endif
-}
-
-/****************************************************************************
- Return the minor devicenumber for UNIX extensions.
-****************************************************************************/
-
-static uint32 unix_dev_minor(SMB_DEV_T dev)
-{
-#if defined(HAVE_DEVICE_MINOR_FN)
- return (uint32)minor(dev);
-#else
- return (uint32)(dev & 0xff);
-#endif
-}
-
/****************************************************************************
Map wire perms onto standard UNIX permissions. Obey share restrictions.
****************************************************************************/
adate &= ~1;
}
- if(mode & aDIR)
+ if(mode & aDIR) {
+ /* This is necessary, as otherwise the
+ * desktop.ini file in this folder is
+ * ignored */
+ mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
file_size = 0;
+ }
DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
****************************************************************************/
static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
- char **pparams, int total_params, char **ppdata, int total_data)
+ char **pparams, int total_params, char **ppdata, int total_data,
+ unsigned int max_data_bytes)
{
/* We must be careful here that we don't return more than the
allowed number of data bytes. If this means returning fewer than
maxentries then so be it. We assume that the redirector has
enough room for the fixed number of parameter bytes it has
requested. */
- uint32 max_data_bytes = SVAL(inbuf, smb_mdrcnt);
char *params = *pparams;
char *pdata = *ppdata;
int dirtype = SVAL(params,0);
int maxentries = SVAL(params,2);
- BOOL close_after_first = BITSETW(params+4,0);
- BOOL close_if_end = BITSETW(params+4,1);
- BOOL requires_resume_key = BITSETW(params+4,2);
+ uint16 findfirst_flags = SVAL(params,4);
+ BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
+ BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
+ BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
int info_level = SVAL(params,6);
pstring directory;
pstring mask;
close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
info_level, max_data_bytes));
-
+
+ if (!maxentries) {
+ /* W2K3 seems to treat zero as 1. */
+ maxentries = 1;
+ }
+
switch (info_level) {
case SMB_INFO_STANDARD:
case SMB_INFO_QUERY_EA_SIZE:
return(ERROR_DOS(ERRDOS,ERRunknownlevel));
}
- srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus);
+ srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, True);
if (!NT_STATUS_IS_OK(ntstatus)) {
return ERROR_NT(ntstatus);
}
RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf);
unix_convert(directory,conn,0,&bad_path,&sbuf);
+ if (bad_path) {
+ return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ }
if(!check_name(directory,conn)) {
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
}
DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
- pdata = Realloc(*ppdata, max_data_bytes + 1024);
+ pdata = Realloc(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
if( pdata == NULL )
return(ERROR_DOS(ERRDOS,ERRnomem));
*ppdata = pdata;
- memset((char *)pdata,'\0',max_data_bytes + 1024);
+ memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
/* Realloc the params space */
params = Realloc(*pparams, 10);
****************************************************************************/
static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
- char **pparams, int total_params, char **ppdata, int total_data)
+ char **pparams, int total_params, char **ppdata, int total_data,
+ unsigned int max_data_bytes)
{
/* We must be careful here that we don't return more than the
allowed number of data bytes. If this means returning fewer than
maxentries then so be it. We assume that the redirector has
enough room for the fixed number of parameter bytes it has
requested. */
- int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
char *params = *pparams;
char *pdata = *ppdata;
int dptr_num = SVAL(params,0);
int maxentries = SVAL(params,2);
uint16 info_level = SVAL(params,4);
uint32 resume_key = IVAL(params,6);
- BOOL close_after_request = BITSETW(params+10,0);
- BOOL close_if_end = BITSETW(params+10,1);
- BOOL requires_resume_key = BITSETW(params+10,2);
- BOOL continue_bit = BITSETW(params+10,3);
+ uint16 findnext_flags = SVAL(params,10);
+ BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
+ BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
+ BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
+ BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
pstring resume_name;
pstring mask;
pstring directory;
*mask = *directory = *resume_name = 0;
- srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus);
+ srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, True);
if (!NT_STATUS_IS_OK(ntstatus)) {
return ERROR_NT(ntstatus);
}
dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
requires_resume_key, resume_key, resume_name, continue_bit, info_level));
+ if (!maxentries) {
+ /* W2K3 seems to treat zero as 1. */
+ maxentries = 1;
+ }
+
switch (info_level) {
case SMB_INFO_STANDARD:
case SMB_INFO_QUERY_EA_SIZE:
return ERROR_DOS(ERRDOS,ERRunknownlevel);
}
- pdata = Realloc( *ppdata, max_data_bytes + 1024);
+ pdata = Realloc( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
if(pdata == NULL)
return ERROR_DOS(ERRDOS,ERRnomem);
*ppdata = pdata;
- memset((char *)pdata,'\0',max_data_bytes + 1024);
+ memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
/* Realloc the params space */
params = Realloc(*pparams, 6*SIZEOFWORD);
* depend on the last file name instead.
*/
- if(requires_resume_key && *resume_name && !continue_bit) {
+ if(*resume_name && !continue_bit) {
/*
* Fix for NT redirector problem triggered by resume key indexes
if(current_pos < 0) {
DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
SeekDir(dirptr, start_pos);
- for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) {
+ for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; ++current_pos) {
/*
* Remember, mangle_map is called by
}
} /* end for */
} /* end if current_pos */
- } /* end if requires_resume_key && !continue_bit */
+ /* Can't find the name. Just resume from where we were... */
+ if (dname == 0) {
+ SeekDir(dirptr, start_pos);
+ }
+ } /* end if resume_name && !continue_bit */
for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
BOOL got_exact_match = False;
Reply to a TRANS2_QFSINFO (query filesystem info).
****************************************************************************/
-static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf,
- int length, int bufsize,
- char **pparams, int total_params, char **ppdata, int total_data)
+static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
+ char **pparams, int total_params, char **ppdata, int total_data,
+ unsigned int max_data_bytes)
{
- int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
char *pdata = *ppdata;
char *params = *pparams;
uint16 info_level = SVAL(params,0);
return ERROR_DOS(ERRSRV,ERRinvdevice);
}
- pdata = Realloc(*ppdata, max_data_bytes + 1024);
+ pdata = Realloc(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
if ( pdata == NULL )
return ERROR_DOS(ERRDOS,ERRnomem);
*ppdata = pdata;
- memset((char *)pdata,'\0',max_data_bytes + 1024);
+ memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
switch (info_level) {
case SMB_INFO_ALLOCATION:
data_len = 12;
SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
- SBIG_UINT(pdata,4,((SMB_BIG_UINT)0)); /* No capabilities for now... */
+ SBIG_UINT(pdata,4,((SMB_BIG_UINT)CIFS_UNIX_POSIX_ACLS_CAP)); /* We have POSIX ACLs. */
break;
case SMB_MAC_QUERY_FS_INFO:
Reply to a TRANS2_SETFSINFO (set filesystem info).
****************************************************************************/
-static int call_trans2setfsinfo(connection_struct *conn,
- char *inbuf, char *outbuf, int length, int bufsize,
- char **pparams, int total_params, char **ppdata, int total_data)
+static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
+ char **pparams, int total_params, char **ppdata, int total_data,
+ unsigned int max_data_bytes)
{
char *pdata = *ppdata;
char *params = *pparams;
#endif /* HAVE_SYS_QUOTAS */
/****************************************************************************
- * Utility function to set bad path error.
- ****************************************************************************/
+ Utility function to set bad path error.
+****************************************************************************/
int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
{
return UNIXERROR(def_class,def_code);
}
+/****************************************************************************
+ Utility function to count the number of entries in a POSIX acl.
+****************************************************************************/
+
+static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
+{
+ unsigned int ace_count = 0;
+ 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)) {
+ /* get_next... */
+ if (entry_id == SMB_ACL_FIRST_ENTRY) {
+ entry_id = SMB_ACL_NEXT_ENTRY;
+ }
+ ace_count++;
+ }
+ return ace_count;
+}
+
+/****************************************************************************
+ Utility function to marshall a POSIX acl into wire format.
+****************************************************************************/
+
+static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
+{
+ 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)) {
+ SMB_ACL_TAG_T tagtype;
+ SMB_ACL_PERMSET_T permset;
+ unsigned char perms = 0;
+ unsigned int own_grp;
+
+ /* get_next... */
+ if (entry_id == SMB_ACL_FIRST_ENTRY) {
+ entry_id = SMB_ACL_NEXT_ENTRY;
+ }
+
+ if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, 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) {
+ 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);
+
+ SCVAL(pdata,1,perms);
+
+ switch (tagtype) {
+ case SMB_ACL_USER_OBJ:
+ SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
+ own_grp = (unsigned int)pst->st_uid;
+ SIVAL(pdata,2,own_grp);
+ SIVAL(pdata,6,0);
+ break;
+ case SMB_ACL_USER:
+ {
+ uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
+ if (!puid) {
+ DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
+ }
+ 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);
+ break;
+ }
+ case SMB_ACL_GROUP_OBJ:
+ SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
+ own_grp = (unsigned int)pst->st_gid;
+ SIVAL(pdata,2,own_grp);
+ SIVAL(pdata,6,0);
+ break;
+ case SMB_ACL_GROUP:
+ {
+ gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
+ if (!pgid) {
+ DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
+ }
+ 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);
+ break;
+ }
+ case SMB_ACL_MASK:
+ SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
+ SIVAL(pdata,2,0xFFFFFFFF);
+ SIVAL(pdata,6,0xFFFFFFFF);
+ break;
+ case SMB_ACL_OTHER:
+ SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
+ SIVAL(pdata,2,0xFFFFFFFF);
+ SIVAL(pdata,6,0xFFFFFFFF);
+ break;
+ default:
+ DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
+ return False;
+ }
+ pdata += SMB_POSIX_ACL_ENTRY_SIZE;
+ }
+
+ return True;
+}
+
/****************************************************************************
Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
file name or file id).
****************************************************************************/
-static int call_trans2qfilepathinfo(connection_struct *conn,
- char *inbuf, char *outbuf, int length,
- int bufsize,
- char **pparams, int total_params, char **ppdata, int total_data)
+static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
+ char **pparams, int total_params, char **ppdata, int total_data,
+ unsigned int max_data_bytes)
{
- int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
char *params = *pparams;
char *pdata = *ppdata;
uint16 tran_call = SVAL(inbuf, smb_setup0);
if (!params)
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ ZERO_STRUCT(sbuf);
+
if (tran_call == TRANSACT2_QFILEINFO) {
if (total_params < 4)
return(ERROR_DOS(ERRDOS,ERRinvalidparam));
*/
pstrcpy(fname, fsp->fsp_name);
- unix_convert(fname,conn,0,&bad_path,&sbuf);
- if (!check_name(fname,conn)) {
- DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed for fake_file(%s)\n",fname,strerror(errno)));
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
- }
+ /* We know this name is ok, it's already passed the checks. */
} else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
/*
* handle (returned from an NT SMB). NT5.0 seems
* to do this call. JRA.
*/
+ /* We know this name is ok, it's already passed the checks. */
pstrcpy(fname, fsp->fsp_name);
- unix_convert(fname,conn,0,&bad_path,&sbuf);
- if (!check_name(fname,conn)) {
- DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
- return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
- }
if (INFO_LEVEL_IS_UNIX(info_level)) {
/* Always do lstat for UNIX calls. */
DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
}
- } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
+ } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
}
- delete_pending = fsp->directory_delete_on_close;
+ delete_pending = fsp->is_directory ? fsp->directory_delete_on_close : 0;
} else {
/*
* Original code - this is an open file.
DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
- srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
unix_convert(fname,conn,0,&bad_path,&sbuf);
+ if (bad_path) {
+ return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ }
if (!check_name(fname,conn)) {
DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
fullpathname = fname;
file_size = get_file_size(sbuf);
allocation_size = get_allocation_size(fsp,&sbuf);
- if (mode & aDIR)
+ if (mode & aDIR) {
+ /* This is necessary, as otherwise the desktop.ini file in
+ * this folder is ignored */
+ mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
file_size = 0;
+ }
params = Realloc(*pparams,2);
if (params == NULL)
return ERROR_DOS(ERRDOS,ERRnomem);
*pparams = params;
memset((char *)params,'\0',2);
- data_size = max_data_bytes + 1024;
+ data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
pdata = Realloc(*ppdata, data_size);
if ( pdata == NULL )
return ERROR_DOS(ERRDOS,ERRnomem);
if (lp_dos_filetime_resolution(SNUM(conn))) {
c_time &= ~1;
sbuf.st_atime &= ~1;
- sbuf.st_mtime &= ~1;
+ sbuf.st_ctime &= ~1;
sbuf.st_mtime &= ~1;
}
case SMB_QUERY_FILE_UNIX_LINK:
{
pstring buffer;
- char *bufp = buffer;
DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
#ifdef S_ISLNK
if (len == -1)
return(UNIXERROR(ERRDOS,ERRnoaccess));
buffer[len] = 0;
- if (strncmp(buffer, CIFS_CLIENT_SYMLINK_STRING, strlen(CIFS_CLIENT_SYMLINK_STRING)) == 0) {
- bufp += strlen(CIFS_CLIENT_SYMLINK_STRING);
- }
-
- len = srvstr_push(outbuf, pdata, bufp, -1, STR_TERMINATE);
+ len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
pdata += len;
data_size = PTR_DIFF(pdata,(*ppdata));
break;
}
+ case SMB_QUERY_POSIX_ACL:
+ {
+ SMB_ACL_T file_acl = NULL;
+ SMB_ACL_T def_acl = NULL;
+ uint16 num_file_acls = 0;
+ uint16 num_def_acls = 0;
+
+ if (fsp && !fsp->is_directory && (fsp->fd != -1)) {
+ file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd);
+ } else {
+ file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
+ }
+
+ if (file_acl == NULL && no_acl_syscall_error(errno)) {
+ DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
+ fname ));
+ return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
+ }
+
+ if (S_ISDIR(sbuf.st_mode)) {
+ if (fsp && fsp->is_directory) {
+ def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
+ } else {
+ def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
+ }
+ def_acl = free_empty_sys_acl(conn, def_acl);
+ }
+
+ num_file_acls = count_acl_entries(conn, file_acl);
+ num_def_acls = count_acl_entries(conn, def_acl);
+
+ if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
+ DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
+ data_size,
+ (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);
+ }
+ if (def_acl) {
+ SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
+ }
+ return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
+ }
+
+ SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
+ SSVAL(pdata,2,num_file_acls);
+ SSVAL(pdata,4,num_def_acls);
+ if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
+ if (file_acl) {
+ SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
+ }
+ if (def_acl) {
+ SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
+ }
+ return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
+ }
+ if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
+ if (file_acl) {
+ SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
+ }
+ if (def_acl) {
+ SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
+ }
+ return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
+ }
+
+ if (file_acl) {
+ SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
+ }
+ if (def_acl) {
+ SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
+ }
+ data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
+ break;
+ }
+
default:
return ERROR_DOS(ERRDOS,ERRunknownlevel);
}
open_file_shared. JRA.
****************************************************************************/
-NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close)
+NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close, uint32 dosmode)
{
- /*
- * Only allow delete on close for writable shares.
- */
+ if (delete_on_close) {
+ /*
+ * Only allow delete on close for writable files.
+ */
- if (delete_on_close && !CAN_WRITE(fsp->conn)) {
- DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
+ if (dosmode & aRONLY) {
+ DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but file attribute is readonly.\n",
fsp->fsp_name ));
- return NT_STATUS_ACCESS_DENIED;
- }
- /*
- * Only allow delete on close for files/directories opened with delete intent.
- */
+ return NT_STATUS_CANNOT_DELETE;
+ }
+
+ /*
+ * Only allow delete on close for writable shares.
+ */
- if (delete_on_close && !(fsp->desired_access & DELETE_ACCESS)) {
- DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
+ if (!CAN_WRITE(fsp->conn)) {
+ DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
fsp->fsp_name ));
- return NT_STATUS_ACCESS_DENIED;
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ /*
+ * Only allow delete on close for files/directories opened with delete intent.
+ */
+
+ if (!(fsp->desired_access & DELETE_ACCESS)) {
+ DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
+ fsp->fsp_name ));
+ return NT_STATUS_ACCESS_DENIED;
+ }
}
if(fsp->is_directory) {
return NT_STATUS_ACCESS_DENIED;
if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
- DEBUG(0,("set_delete_on_close_internal: failed to change delete on close flag for file %s\n",
+ DEBUG(0,("set_delete_on_close_over_all: failed to change delete on close flag for file %s\n",
fsp->fsp_name ));
unlock_share_entry_fsp(fsp);
return NT_STATUS_ACCESS_DENIED;
return NT_STATUS_OK;
}
-/****************************************************************************
- Returns true if this pathname is within the share, and thus safe.
-****************************************************************************/
-
-static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in, char *link_dest_out)
-{
-#ifdef PATH_MAX
- char resolved_name[PATH_MAX+1];
-#else
- pstring resolved_name;
-#endif
- fstring last_component;
- pstring link_dest;
- pstring link_test;
- char *p;
- BOOL bad_path = False;
- SMB_STRUCT_STAT sbuf;
-
- pstrcpy(link_dest, link_dest_in);
- unix_convert(link_dest,conn,0,&bad_path,&sbuf);
-
- /* Store the UNIX converted path. */
- pstrcpy(link_dest_out, link_dest);
-
- p = strrchr_m(link_dest, '/');
- if (p) {
- fstrcpy(last_component, p+1);
- *p = '\0';
- } else {
- fstrcpy(last_component, link_dest);
- pstrcpy(link_dest, "./");
- }
-
- if (SMB_VFS_REALPATH(conn,link_dest,resolved_name) == NULL)
- return -1;
-
- DEBUG(10,("ensure_link_is_safe: realpath: link_dest (%s) -> real name (%s)\n",
- link_dest, resolved_name ));
-
- pstrcpy(link_dest, resolved_name);
- pstrcat(link_dest, "/");
- pstrcat(link_dest, last_component);
-
- if (*link_dest != '/') {
- /* Relative path. */
- pstrcpy(link_test, conn->connectpath);
- pstrcat(link_test, "/");
- pstrcat(link_test, link_dest);
- } else {
- pstrcpy(link_test, link_dest);
- }
-
- DEBUG(10,("ensure_link_is_safe: connectpath = %s, absolute resolved path = %s\n",
- conn->connectpath, link_test ));
-
- /*
- * Check if the link is within the share.
- */
-
- if (strncmp(conn->connectpath, link_test, strlen(conn->connectpath))) {
- errno = EACCES;
- return -1;
- }
- return 0;
-}
-
/****************************************************************************
Set a hard link (called by UNIX extensions and by NT rename with HARD link
code.
BOOL bad_path_oldname = False;
BOOL bad_path_newname = False;
SMB_STRUCT_STAT sbuf1, sbuf2;
- BOOL rc, rcdest;
pstring last_component_oldname;
pstring last_component_newname;
NTSTATUS status = NT_STATUS_OK;
return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
}
- rc = unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
- if (!rc && bad_path_oldname) {
+ unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
+ if (bad_path_oldname) {
return NT_STATUS_OBJECT_PATH_NOT_FOUND;
}
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
- rcdest = unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
- if (!rcdest && bad_path_newname) {
+ if (!check_name(oldname,conn)) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
+ unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
+ if (bad_path_newname) {
return NT_STATUS_OBJECT_PATH_NOT_FOUND;
}
return NT_STATUS_OBJECT_NAME_COLLISION;
}
+ if (!check_name(newname,conn)) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
/* No links from a directory. */
if (S_ISDIR(sbuf1.st_mode)) {
return NT_STATUS_FILE_IS_A_DIRECTORY;
}
- if (ensure_link_is_safe(conn, oldname, oldname) != 0)
+ /* Ensure this is within the share. */
+ if (!reduce_name(conn, oldname) != 0)
return NT_STATUS_ACCESS_DENIED;
DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
Reply to a TRANS2_SETFILEINFO (set file info by fileid).
****************************************************************************/
-static int call_trans2setfilepathinfo(connection_struct *conn,
- char *inbuf, char *outbuf, int length, int bufsize,
- char **pparams, int total_params, char **ppdata, int total_data)
+static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
+ char **pparams, int total_params, char **ppdata, int total_data,
+ unsigned int max_data_bytes)
{
char *params = *pparams;
char *pdata = *ppdata;
if (!params)
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ ZERO_STRUCT(sbuf);
+
if (tran_call == TRANSACT2_SETFILEINFO) {
if (total_params < 4)
return(ERROR_DOS(ERRDOS,ERRinvalidparam));
* to do this call. JRA.
*/
pstrcpy(fname, fsp->fsp_name);
- unix_convert(fname,conn,0,&bad_path,&sbuf);
- if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) {
+ if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
}
return(ERROR_DOS(ERRDOS,ERRinvalidparam));
info_level = SVAL(params,0);
- srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
unix_convert(fname,conn,0,&bad_path,&sbuf);
+ if (bad_path) {
+ return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ }
/*
* For CIFS UNIX extensions the target name may not exist.
SSVAL(params,0,0);
- if (fsp) {
+ if (fsp && fsp->pending_modtime) {
/* the pending modtime overrides the current modtime */
sbuf.st_mtime = fsp->pending_modtime;
}
fname, (double)allocation_size ));
if (allocation_size)
- allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
+ allocation_size = smb_roundup(allocation_size);
if(allocation_size != get_file_size(sbuf)) {
SMB_STRUCT_STAT new_sbuf;
SET_OPEN_MODE(DOS_OPEN_RDWR),
(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
FILE_ATTRIBUTE_NORMAL,
- 0, &access_mode, &action);
+ INTERNAL_OPEN_ONLY, &access_mode, &action);
if (new_fsp == NULL)
return(UNIXERROR(ERRDOS,ERRbadpath));
if (fsp == NULL)
return(UNIXERROR(ERRDOS,ERRbadfid));
- status = set_delete_on_close_internal(fsp, delete_on_close);
+ status = set_delete_on_close_internal(fsp, delete_on_close, dosmode);
if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK))
return ERROR_NT(status);
* a new info level should be used for mknod. JRA.
*/
-#if !defined(HAVE_MAKEDEV_FN)
- return(ERROR_DOS(ERRDOS,ERRnoaccess));
-#else /* HAVE_MAKEDEV_FN */
uint32 file_type = IVAL(pdata,0);
+#if defined(HAVE_MAKEDEV)
uint32 dev_major = IVAL(pdata,4);
uint32 dev_minor = IVAL(pdata,12);
+#endif
uid_t myuid = geteuid();
gid_t mygid = getegid();
- SMB_DEV_T dev;
+ SMB_DEV_T dev = (SMB_DEV_T)0;
if (tran_call == TRANSACT2_SETFILEINFO)
return(ERROR_DOS(ERRDOS,ERRnoaccess));
if (raw_unixmode == SMB_MODE_NO_CHANGE)
return(ERROR_DOS(ERRDOS,ERRinvalidparam));
+#if defined(HAVE_MAKEDEV)
dev = makedev(dev_major, dev_minor);
+#endif
/* We can only create as the owner/group we are. */
if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
return(ERROR_DOS(ERRDOS,ERRnoaccess));
- if (file_type != UNIX_TYPE_CHARDEV && file_type != UNIX_TYPE_BLKDEV &&
- file_type != UNIX_TYPE_FIFO)
- return(ERROR_DOS(ERRDOS,ERRnoaccess));
+ switch (file_type) {
+#if defined(S_IFIFO)
+ case UNIX_TYPE_FIFO:
+ unixmode |= S_IFIFO;
+ break;
+#endif
+#if defined(S_IFSOCK)
+ case UNIX_TYPE_SOCKET:
+ unixmode |= S_IFSOCK;
+ break;
+#endif
+#if defined(S_IFCHR)
+ case UNIX_TYPE_CHARDEV:
+ unixmode |= S_IFCHR;
+ break;
+#endif
+#if defined(S_IFBLK)
+ case UNIX_TYPE_BLKDEV:
+ unixmode |= S_IFBLK;
+ break;
+#endif
+ default:
+ return(ERROR_DOS(ERRDOS,ERRnoaccess));
+ }
DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
0%o for file %s\n", (double)dev, unixmode, fname ));
/* Ok - do the mknod. */
- if (SMB_VFS_MKNOD(conn,dos_to_unix_static(fname), unixmode, dev) != 0)
+ if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
return(UNIXERROR(ERRDOS,ERRnoaccess));
inherit_access_acl(conn, fname, unixmode);
SSVAL(params,0,0);
send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
return(-1);
-#endif /* HAVE_MAKEDEV_FN */
-
}
/*
case SMB_SET_FILE_UNIX_LINK:
{
- pstring oldname;
+ pstring link_target;
char *newname = fname;
- BOOL cifs_client_link = False;
/* Set a symbolic link. */
/* Don't allow this if follow links is false. */
if (!lp_symlinks(SNUM(conn)))
return(ERROR_DOS(ERRDOS,ERRnoaccess));
- srvstr_pull(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE);
- unix_format(oldname);
+ srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
- if (*oldname == '/') {
- /* Absolute paths are automatically a client resolved link. */
- cifs_client_link = True;
- } else {
+ /* !widelinks forces the target path to be within the share. */
+ /* This means we can interpret the target as a pathname. */
+ if (!lp_widelinks(SNUM(conn))) {
pstring rel_name;
char *last_dirp = NULL;
+ unix_format(link_target);
+ if (*link_target == '/') {
+ /* No absolute paths allowed. */
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
pstrcpy(rel_name, newname);
last_dirp = strrchr_m(rel_name, '/');
if (last_dirp) {
} else {
pstrcpy(rel_name, "./");
}
- pstrcat(rel_name, oldname);
- if (ensure_link_is_safe(conn, rel_name, rel_name) != 0)
- cifs_client_link = True;
+ pstrcat(rel_name, link_target);
- }
-
- if (cifs_client_link) {
- pstring tmp_name;
- pstrcpy(tmp_name, CIFS_CLIENT_SYMLINK_STRING);
- pstrcat(tmp_name, oldname);
- pstrcpy(oldname, tmp_name);
+ if (!check_name(rel_name, conn)) {
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
}
DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
- fname, oldname ));
+ fname, link_target ));
- if (SMB_VFS_SYMLINK(conn,oldname,newname) != 0)
+ if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
return(UNIXERROR(ERRDOS,ERRnoaccess));
SSVAL(params,0,0);
send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
char *newname = fname;
/* Set a hard link. */
- srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status, False);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
overwrite = (CVAL(pdata,0) ? True : False);
root_fid = IVAL(pdata,4);
len = IVAL(pdata,8);
- srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
+ srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, False);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
if (fsp) {
DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
fsp->fnum, fsp->fsp_name, base_name ));
- status = rename_internals_fsp(conn, fsp, base_name, overwrite);
+ status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
} else {
DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
fname, newname ));
send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
return(-1);
}
+
+ case SMB_SET_POSIX_ACL:
+ {
+ uint16 posix_acl_version;
+ uint16 num_file_acls;
+ uint16 num_def_acls;
+ BOOL valid_file_acls = True;
+ BOOL valid_def_acls = True;
+
+ if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
+ return(ERROR_DOS(ERRDOS,ERRinvalidparam));
+ }
+ posix_acl_version = SVAL(pdata,0);
+ num_file_acls = SVAL(pdata,2);
+ num_def_acls = SVAL(pdata,4);
+
+ if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
+ valid_file_acls = False;
+ num_file_acls = 0;
+ }
+
+ if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
+ valid_def_acls = False;
+ num_def_acls = 0;
+ }
+
+ if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
+ return(ERROR_DOS(ERRDOS,ERRinvalidparam));
+ }
+
+ if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
+ (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
+ return(ERROR_DOS(ERRDOS,ERRinvalidparam));
+ }
+
+ if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
+ pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
+
+ if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
+ pdata + SMB_POSIX_ACL_HEADER_SIZE +
+ (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
+
+ SSVAL(params,0,0);
+ send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
+ return(-1);
+ }
+
default:
return ERROR_DOS(ERRDOS,ERRunknownlevel);
}
SET_OPEN_MODE(DOS_OPEN_RDWR),
(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
FILE_ATTRIBUTE_NORMAL,
- 0, &access_mode, &action);
+ INTERNAL_OPEN_ONLY, &access_mode, &action);
if (new_fsp == NULL)
return(UNIXERROR(ERRDOS,ERRbadpath));
Reply to a TRANS2_MKDIR (make directory with extended attributes).
****************************************************************************/
-static int call_trans2mkdir(connection_struct *conn,
- char *inbuf, char *outbuf, int length, int bufsize,
- char **pparams, int total_params, char **ppdata, int total_data)
+static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
+ char **pparams, int total_params, char **ppdata, int total_data,
+ unsigned int max_data_bytes)
{
char *params = *pparams;
pstring directory;
if (total_params < 4)
return(ERROR_DOS(ERRDOS,ERRinvalidparam));
- srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE, &status, False);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
unix_convert(directory,conn,0,&bad_path,&sbuf);
+ if (bad_path) {
+ return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ }
if (check_name(directory,conn))
ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
We don't actually do this - we just send a null response.
****************************************************************************/
-static int call_trans2findnotifyfirst(connection_struct *conn,
- char *inbuf, char *outbuf, int length, int bufsize,
- char **pparams, int total_params, char **ppdata, int total_data)
+static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
+ char **pparams, int total_params, char **ppdata, int total_data,
+ unsigned int max_data_bytes)
{
static uint16 fnf_handle = 257;
char *params = *pparams;
changes). Currently this does nothing.
****************************************************************************/
-static int call_trans2findnotifynext(connection_struct *conn,
- char *inbuf, char *outbuf, int length, int bufsize,
- char **pparams, int total_params, char **ppdata, int total_data)
+static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
+ char **pparams, int total_params, char **ppdata, int total_data,
+ unsigned int max_data_bytes)
{
char *params = *pparams;
Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
****************************************************************************/
-static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf,
- char* outbuf, int length, int bufsize,
- char **pparams, int total_params, char **ppdata, int total_data)
+static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
+ char **pparams, int total_params, char **ppdata, int total_data,
+ unsigned int max_data_bytes)
{
char *params = *pparams;
pstring pathname;
Reply to a TRANS2_IOCTL - used for OS/2 printing.
****************************************************************************/
-static int call_trans2ioctl(connection_struct *conn, char* inbuf,
- char* outbuf, int length, int bufsize,
- char **pparams, int total_params, char **ppdata, int total_data)
+static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
+ char **pparams, int total_params, char **ppdata, int total_data,
+ unsigned int max_data_bytes)
{
char *pdata = *ppdata;
files_struct *fsp = file_fsp(inbuf,smb_vwv15);
int outsize = 0;
unsigned int total_params = SVAL(inbuf, smb_tpscnt);
unsigned int total_data =SVAL(inbuf, smb_tdscnt);
+ unsigned int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
#if 0
unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
- unsigned int max_data_reply = SVAL(inbuf, smb_mdrcnt);
unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
BOOL close_tid = BITSETW(inbuf+smb_flags,0);
BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
goto bad_param;
if (num_params) {
- if (param_disp + num_params >= total_params)
+ if (param_disp + num_params > total_params)
goto bad_param;
if ((param_disp + num_params < param_disp) ||
(param_disp + num_params < num_params))
memcpy( ¶ms[param_disp], smb_base(inbuf) + param_off, num_params);
}
if (num_data) {
- if (data_disp + num_data >= total_data)
+ if (data_disp + num_data > total_data)
goto bad_param;
if ((data_disp + num_data < data_disp) ||
(data_disp + num_data < num_data))
case TRANSACT2_OPEN:
START_PROFILE_NESTED(Trans2_open);
outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
- ¶ms, total_params, &data, total_data);
+ ¶ms, total_params, &data, total_data, max_data_bytes);
END_PROFILE_NESTED(Trans2_open);
break;
case TRANSACT2_FINDFIRST:
START_PROFILE_NESTED(Trans2_findfirst);
outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
- ¶ms, total_params, &data, total_data);
+ ¶ms, total_params, &data, total_data, max_data_bytes);
END_PROFILE_NESTED(Trans2_findfirst);
break;
case TRANSACT2_FINDNEXT:
START_PROFILE_NESTED(Trans2_findnext);
outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
- ¶ms, total_params, &data, total_data);
+ ¶ms, total_params, &data, total_data, max_data_bytes);
END_PROFILE_NESTED(Trans2_findnext);
break;
case TRANSACT2_QFSINFO:
START_PROFILE_NESTED(Trans2_qfsinfo);
outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
- ¶ms, total_params, &data, total_data);
+ ¶ms, total_params, &data, total_data, max_data_bytes);
END_PROFILE_NESTED(Trans2_qfsinfo);
break;
case TRANSACT2_SETFSINFO:
START_PROFILE_NESTED(Trans2_setfsinfo);
outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
- ¶ms, total_params, &data, total_data);
+ ¶ms, total_params, &data, total_data, max_data_bytes);
END_PROFILE_NESTED(Trans2_setfsinfo);
break;
#endif
case TRANSACT2_QFILEINFO:
START_PROFILE_NESTED(Trans2_qpathinfo);
outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
- ¶ms, total_params, &data, total_data);
+ ¶ms, total_params, &data, total_data, max_data_bytes);
END_PROFILE_NESTED(Trans2_qpathinfo);
break;
case TRANSACT2_SETPATHINFO:
case TRANSACT2_SETFILEINFO:
START_PROFILE_NESTED(Trans2_setpathinfo);
outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
- ¶ms, total_params, &data, total_data);
+ ¶ms, total_params, &data, total_data, max_data_bytes);
END_PROFILE_NESTED(Trans2_setpathinfo);
break;
case TRANSACT2_FINDNOTIFYFIRST:
START_PROFILE_NESTED(Trans2_findnotifyfirst);
outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
- ¶ms, total_params, &data, total_data);
+ ¶ms, total_params, &data, total_data, max_data_bytes);
END_PROFILE_NESTED(Trans2_findnotifyfirst);
break;
case TRANSACT2_FINDNOTIFYNEXT:
START_PROFILE_NESTED(Trans2_findnotifynext);
outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
- ¶ms, total_params, &data, total_data);
+ ¶ms, total_params, &data, total_data, max_data_bytes);
END_PROFILE_NESTED(Trans2_findnotifynext);
break;
case TRANSACT2_MKDIR:
START_PROFILE_NESTED(Trans2_mkdir);
outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
- ¶ms, total_params, &data, total_data);
+ ¶ms, total_params, &data, total_data, max_data_bytes);
END_PROFILE_NESTED(Trans2_mkdir);
break;
case TRANSACT2_GET_DFS_REFERRAL:
START_PROFILE_NESTED(Trans2_get_dfs_referral);
outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
- ¶ms, total_params, &data, total_data);
+ ¶ms, total_params, &data, total_data, max_data_bytes);
END_PROFILE_NESTED(Trans2_get_dfs_referral);
break;
case TRANSACT2_IOCTL:
START_PROFILE_NESTED(Trans2_ioctl);
outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
- ¶ms, total_params, &data, total_data);
+ ¶ms, total_params, &data, total_data, max_data_bytes);
END_PROFILE_NESTED(Trans2_ioctl);
break;
default: