mirror of
https://github.com/samba-team/samba.git
synced 2025-01-13 13:18:06 +03:00
r20844: Somewhat radical change - this may break the build (I will
watch carefully - so I'm doing it in one transaction so I can roll back). Change check_name(), reduce_name() and dptr_create() to return NTSTATUS. This helps a lot in error path processing and especially in reduce_name() allows us to ditch the flaky and error-prone saving of errno and return errors directly. Jeremy.
This commit is contained in:
parent
a36d446fb6
commit
6133a694aa
@ -2073,7 +2073,8 @@ WERROR _srvsvc_NetGetFileSecurity(pipes_struct *p, const char *server_unc, const
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
if (!check_name(file,conn)) {
|
||||
nt_status = check_name(conn, file);
|
||||
if (!NT_STATUS_IS_OK(nt_status)) {
|
||||
DEBUG(3,("_srv_net_file_query_secdesc: can't access %s\n", file));
|
||||
status = WERR_ACCESS_DENIED;
|
||||
goto error_exit;
|
||||
@ -2176,7 +2177,8 @@ WERROR _srvsvc_NetSetFileSecurity(pipes_struct *p, const char *server_unc, const
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
if (!check_name(file,conn)) {
|
||||
nt_status = check_name(conn, file);
|
||||
if (!NT_STATUS_IS_OK(nt_status)) {
|
||||
DEBUG(3,("_srv_net_file_set_secdesc: can't access %s\n", file));
|
||||
status = WERR_ACCESS_DENIED;
|
||||
goto error_exit;
|
||||
|
@ -382,21 +382,26 @@ static void dptr_close_oldest(BOOL old)
|
||||
wcard must not be zero.
|
||||
****************************************************************************/
|
||||
|
||||
int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid,
|
||||
const char *wcard, BOOL wcard_has_wild, uint32 attr)
|
||||
NTSTATUS dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid,
|
||||
const char *wcard, BOOL wcard_has_wild, uint32 attr, int *dptr_hnd_ret)
|
||||
{
|
||||
struct dptr_struct *dptr = NULL;
|
||||
struct smb_Dir *dir_hnd;
|
||||
const char *dir2;
|
||||
NTSTATUS status;
|
||||
|
||||
DEBUG(5,("dptr_create dir=%s\n", path));
|
||||
|
||||
*dptr_hnd_ret = -1;
|
||||
|
||||
if (!wcard) {
|
||||
return -1;
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!check_name(path,conn))
|
||||
return(-2); /* Code to say use a unix error return code. */
|
||||
status = check_name(conn,path);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
/* use a const pointer from here on */
|
||||
dir2 = path;
|
||||
@ -405,19 +410,20 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp
|
||||
|
||||
dir_hnd = OpenDir(conn, dir2, wcard, attr);
|
||||
if (!dir_hnd) {
|
||||
return (-2);
|
||||
return map_nt_error_from_unix(errno);
|
||||
}
|
||||
|
||||
string_set(&conn->dirpath,dir2);
|
||||
|
||||
if (dirhandles_open >= MAX_OPEN_DIRECTORIES)
|
||||
if (dirhandles_open >= MAX_OPEN_DIRECTORIES) {
|
||||
dptr_idleoldest();
|
||||
}
|
||||
|
||||
dptr = SMB_MALLOC_P(struct dptr_struct);
|
||||
if(!dptr) {
|
||||
DEBUG(0,("malloc fail in dptr_create.\n"));
|
||||
CloseDir(dir_hnd);
|
||||
return -1;
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
ZERO_STRUCTP(dptr);
|
||||
@ -447,7 +453,7 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp
|
||||
DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum));
|
||||
SAFE_FREE(dptr);
|
||||
CloseDir(dir_hnd);
|
||||
return -1;
|
||||
return NT_STATUS_TOO_MANY_OPENED_FILES;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -477,7 +483,7 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp
|
||||
DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum));
|
||||
SAFE_FREE(dptr);
|
||||
CloseDir(dir_hnd);
|
||||
return -1;
|
||||
return NT_STATUS_TOO_MANY_OPENED_FILES;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -496,7 +502,7 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp
|
||||
bitmap_clear(dptr_bmap, dptr->dnum - 1);
|
||||
SAFE_FREE(dptr);
|
||||
CloseDir(dir_hnd);
|
||||
return -1;
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
if (lp_posix_pathnames() || (wcard[0] == '.' && wcard[1] == 0)) {
|
||||
dptr->has_wild = True;
|
||||
@ -513,7 +519,8 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp
|
||||
|
||||
conn->dirptr = dptr;
|
||||
|
||||
return(dptr->dnum);
|
||||
*dptr_hnd_ret = dptr->dnum;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
@ -512,28 +512,25 @@ NTSTATUS unix_convert(connection_struct *conn,
|
||||
a valid one for the user to access.
|
||||
****************************************************************************/
|
||||
|
||||
BOOL check_name(const pstring name,connection_struct *conn)
|
||||
NTSTATUS check_name(connection_struct *conn, const pstring name)
|
||||
{
|
||||
BOOL ret = True;
|
||||
|
||||
if (IS_VETO_PATH(conn, name)) {
|
||||
/* Is it not dot or dot dot. */
|
||||
if (!((name[0] == '.') && (!name[1] || (name[1] == '.' && !name[2])))) {
|
||||
DEBUG(5,("file path name %s vetoed\n",name));
|
||||
errno = ENOENT;
|
||||
return False;
|
||||
DEBUG(5,("check_name: file path name %s vetoed\n",name));
|
||||
return map_nt_error_from_unix(ENOENT);
|
||||
}
|
||||
}
|
||||
|
||||
if (!lp_widelinks(SNUM(conn)) || !lp_symlinks(SNUM(conn))) {
|
||||
ret = reduce_name(conn,name);
|
||||
NTSTATUS status = reduce_name(conn,name);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(5,("check_name: name %s failed with %s\n",name, nt_errstr(status)));
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
DEBUG(5,("check_name on %s failed\n",name));
|
||||
}
|
||||
|
||||
return(ret);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -634,10 +634,11 @@ int reply_ntcreate_and_X(connection_struct *conn,
|
||||
return ERROR_NT(status);
|
||||
}
|
||||
/* All file access must go through check_name() */
|
||||
if (!check_name(fname,conn)) {
|
||||
status = check_name(conn, fname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
restore_case_semantics(conn, file_attributes);
|
||||
END_PROFILE(SMBntcreateX);
|
||||
return UNIXERROR(ERRDOS,ERRbadpath);
|
||||
return ERROR_NT(status);
|
||||
}
|
||||
|
||||
/* This is the correct thing to do (check every time) but can_delete is
|
||||
@ -1259,9 +1260,10 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
|
||||
return ERROR_NT(status);
|
||||
}
|
||||
/* All file access must go through check_name() */
|
||||
if (!check_name(fname,conn)) {
|
||||
status = check_name(conn, fname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
restore_case_semantics(conn, file_attributes);
|
||||
return UNIXERROR(ERRDOS,ERRbadpath);
|
||||
return ERROR_NT(status);
|
||||
}
|
||||
|
||||
/* This is the correct thing to do (check every time) but can_delete is
|
||||
@ -1570,8 +1572,9 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
|
||||
ZERO_STRUCT(sbuf1);
|
||||
ZERO_STRUCT(sbuf2);
|
||||
|
||||
if (!CAN_WRITE(conn))
|
||||
if (!CAN_WRITE(conn)) {
|
||||
return NT_STATUS_MEDIA_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
@ -1582,8 +1585,9 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
|
||||
if (!VALID_STAT(sbuf1)) {
|
||||
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
if (!check_name(oldname,conn)) {
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
status = check_name(conn, oldname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Ensure attributes match. */
|
||||
@ -1602,8 +1606,9 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
|
||||
return NT_STATUS_OBJECT_NAME_COLLISION;
|
||||
}
|
||||
|
||||
if (!check_name(newname,conn)) {
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
status = check_name(conn, newname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
/* No links from a directory. */
|
||||
@ -1612,8 +1617,9 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
|
||||
}
|
||||
|
||||
/* Ensure this is within the share. */
|
||||
if (!reduce_name(conn, oldname) != 0) {
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
status = reduce_name(conn, oldname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
DEBUG(10,("copy_internals: doing file copy %s to %s\n", oldname, newname));
|
||||
|
@ -638,42 +638,53 @@ int reply_checkpath(connection_struct *conn, char *inbuf,char *outbuf, int dum_s
|
||||
|
||||
status = unix_convert(conn, name, False, NULL, &sbuf);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
END_PROFILE(SMBcheckpath);
|
||||
status = map_checkpath_error(inbuf, status);
|
||||
return ERROR_NT(status);
|
||||
goto path_err;
|
||||
}
|
||||
|
||||
if (check_name(name,conn) && (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)) {
|
||||
if (!S_ISDIR(sbuf.st_mode)) {
|
||||
END_PROFILE(SMBcheckpath);
|
||||
return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
|
||||
}
|
||||
} else {
|
||||
/* We special case this - as when a Windows machine
|
||||
is parsing a path is steps through the components
|
||||
one at a time - if a component fails it expects
|
||||
ERRbadpath, not ERRbadfile.
|
||||
*/
|
||||
if(errno == ENOENT) {
|
||||
/*
|
||||
* Windows returns different error codes if
|
||||
* the parent directory is valid but not the
|
||||
* last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
|
||||
* for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
|
||||
* if the path is invalid.
|
||||
*/
|
||||
END_PROFILE(SMBcheckpath);
|
||||
return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
|
||||
}
|
||||
status = check_name(conn, name);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
|
||||
goto path_err;
|
||||
}
|
||||
|
||||
if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
|
||||
DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
|
||||
status = map_nt_error_from_unix(errno);
|
||||
goto path_err;
|
||||
}
|
||||
|
||||
if (!S_ISDIR(sbuf.st_mode)) {
|
||||
END_PROFILE(SMBcheckpath);
|
||||
return(UNIXERROR(ERRDOS,ERRbadpath));
|
||||
return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
|
||||
}
|
||||
|
||||
outsize = set_message(outbuf,0,0,False);
|
||||
|
||||
END_PROFILE(SMBcheckpath);
|
||||
return outsize;
|
||||
|
||||
path_err:
|
||||
|
||||
END_PROFILE(SMBcheckpath);
|
||||
|
||||
/* We special case this - as when a Windows machine
|
||||
is parsing a path is steps through the components
|
||||
one at a time - if a component fails it expects
|
||||
ERRbadpath, not ERRbadfile.
|
||||
*/
|
||||
status = map_checkpath_error(inbuf, status);
|
||||
if(NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
|
||||
/*
|
||||
* Windows returns different error codes if
|
||||
* the parent directory is valid but not the
|
||||
* last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
|
||||
* for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
|
||||
* if the path is invalid.
|
||||
*/
|
||||
return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
|
||||
}
|
||||
|
||||
return ERROR_NT(status);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -717,19 +728,23 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
|
||||
END_PROFILE(SMBgetatr);
|
||||
return ERROR_NT(status);
|
||||
}
|
||||
if (check_name(fname,conn) &&
|
||||
(VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0)) {
|
||||
mode = dos_mode(conn,fname,&sbuf);
|
||||
size = sbuf.st_size;
|
||||
mtime = sbuf.st_mtime;
|
||||
if (mode & aDIR) {
|
||||
size = 0;
|
||||
}
|
||||
} else {
|
||||
DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
|
||||
status = check_name(conn, fname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
|
||||
END_PROFILE(SMBgetatr);
|
||||
return ERROR_NT(status);
|
||||
}
|
||||
if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
|
||||
DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
|
||||
return UNIXERROR(ERRDOS,ERRbadfile);
|
||||
}
|
||||
|
||||
mode = dos_mode(conn,fname,&sbuf);
|
||||
size = sbuf.st_size;
|
||||
mtime = sbuf.st_mtime;
|
||||
if (mode & aDIR) {
|
||||
size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
outsize = set_message(outbuf,10,0,True);
|
||||
@ -792,9 +807,10 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
|
||||
return ERROR_NT(NT_STATUS_ACCESS_DENIED);
|
||||
}
|
||||
|
||||
if (!check_name(fname,conn)) {
|
||||
status = check_name(conn, fname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
END_PROFILE(SMBsetatr);
|
||||
return UNIXERROR(ERRDOS, ERRnoaccess);
|
||||
return ERROR_NT(status);
|
||||
}
|
||||
|
||||
mode = SVAL(inbuf,smb_vwv0);
|
||||
@ -950,9 +966,10 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
|
||||
}
|
||||
unix_format(dir2);
|
||||
|
||||
if (!check_name(directory,conn)) {
|
||||
nt_status = check_name(conn, directory);
|
||||
if (!NT_STATUS_IS_OK(nt_status)) {
|
||||
END_PROFILE(SMBsearch);
|
||||
return UNIXERROR(ERRDOS, ERRnoaccess);
|
||||
return ERROR_NT(nt_status);
|
||||
}
|
||||
|
||||
p = strrchr_m(dir2,'/');
|
||||
@ -996,14 +1013,9 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
|
||||
p = smb_buf(outbuf) + 3;
|
||||
|
||||
if (status_len == 0) {
|
||||
dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype);
|
||||
if (dptr_num < 0) {
|
||||
if(dptr_num == -2) {
|
||||
END_PROFILE(SMBsearch);
|
||||
return UNIXERROR(ERRDOS, ERRnofids);
|
||||
}
|
||||
END_PROFILE(SMBsearch);
|
||||
return ERROR_DOS(ERRDOS,ERRnofids);
|
||||
nt_status = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype,&dptr_num);
|
||||
if (!NT_STATUS_IS_OK(nt_status)) {
|
||||
return ERROR_NT(nt_status);
|
||||
}
|
||||
} else {
|
||||
dirtype = dptr_attr(dptr_num);
|
||||
@ -1839,66 +1851,73 @@ NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
|
||||
dirtype = FILE_ATTRIBUTE_NORMAL;
|
||||
}
|
||||
status = can_delete(conn,directory,dirtype,can_defer);
|
||||
if (!NT_STATUS_IS_OK(status))
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (SMB_VFS_UNLINK(conn,directory) == 0) {
|
||||
count++;
|
||||
}
|
||||
} else {
|
||||
struct smb_Dir *dir_hnd = NULL;
|
||||
long offset = 0;
|
||||
const char *dname;
|
||||
|
||||
if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
|
||||
return NT_STATUS_OBJECT_NAME_INVALID;
|
||||
}
|
||||
|
||||
if (strequal(mask,"????????.???"))
|
||||
if (strequal(mask,"????????.???")) {
|
||||
pstrcpy(mask,"*");
|
||||
}
|
||||
|
||||
if (check_name(directory,conn))
|
||||
dir_hnd = OpenDir(conn, directory, mask, dirtype);
|
||||
status = check_name(conn, directory);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
dir_hnd = OpenDir(conn, directory, mask, dirtype);
|
||||
if (dir_hnd == NULL) {
|
||||
return map_nt_error_from_unix(errno);
|
||||
}
|
||||
|
||||
/* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
|
||||
the pattern matches against the long name, otherwise the short name
|
||||
We don't implement this yet XXXX
|
||||
*/
|
||||
|
||||
if (dir_hnd) {
|
||||
long offset = 0;
|
||||
status = NT_STATUS_NO_SUCH_FILE;
|
||||
status = NT_STATUS_NO_SUCH_FILE;
|
||||
|
||||
while ((dname = ReadDirName(dir_hnd, &offset))) {
|
||||
SMB_STRUCT_STAT st;
|
||||
pstring fname;
|
||||
pstrcpy(fname,dname);
|
||||
while ((dname = ReadDirName(dir_hnd, &offset))) {
|
||||
SMB_STRUCT_STAT st;
|
||||
pstring fname;
|
||||
pstrcpy(fname,dname);
|
||||
|
||||
if (!is_visible_file(conn, directory, dname, &st, True)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Quick check for "." and ".." */
|
||||
if (fname[0] == '.') {
|
||||
if (!fname[1] || (fname[1] == '.' && !fname[2])) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if(!mask_match(fname, mask, conn->case_sensitive))
|
||||
continue;
|
||||
|
||||
slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
|
||||
status = can_delete(conn, fname, dirtype,
|
||||
can_defer);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
continue;
|
||||
}
|
||||
if (SMB_VFS_UNLINK(conn,fname) == 0)
|
||||
count++;
|
||||
DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
|
||||
if (!is_visible_file(conn, directory, dname, &st, True)) {
|
||||
continue;
|
||||
}
|
||||
CloseDir(dir_hnd);
|
||||
|
||||
/* Quick check for "." and ".." */
|
||||
if (fname[0] == '.') {
|
||||
if (!fname[1] || (fname[1] == '.' && !fname[2])) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if(!mask_match(fname, mask, conn->case_sensitive)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
|
||||
status = can_delete(conn, fname, dirtype, can_defer);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
continue;
|
||||
}
|
||||
if (SMB_VFS_UNLINK(conn,fname) == 0)
|
||||
count++;
|
||||
DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
|
||||
}
|
||||
CloseDir(dir_hnd);
|
||||
}
|
||||
|
||||
if (count == 0 && NT_STATUS_IS_OK(status)) {
|
||||
@ -3789,9 +3808,10 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
|
||||
return ERROR_NT(status);
|
||||
}
|
||||
|
||||
if (!check_name(directory,conn)) {
|
||||
status = check_name(conn, directory);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
END_PROFILE(SMBrmdir);
|
||||
return UNIXERROR(ERRDOS, ERRbadpath);
|
||||
return ERROR_NT(status);
|
||||
}
|
||||
|
||||
dptr_closepath(directory,SVAL(inbuf,smb_pid));
|
||||
@ -4267,10 +4287,11 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
|
||||
}
|
||||
|
||||
TALLOC_FREE(lck);
|
||||
if (errno == ENOTDIR || errno == EISDIR)
|
||||
if (errno == ENOTDIR || errno == EISDIR) {
|
||||
status = NT_STATUS_OBJECT_NAME_COLLISION;
|
||||
else
|
||||
} else {
|
||||
status = map_nt_error_from_unix(errno);
|
||||
}
|
||||
|
||||
DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
|
||||
nt_errstr(status), directory,newname));
|
||||
@ -4282,98 +4303,105 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
|
||||
*/
|
||||
struct smb_Dir *dir_hnd = NULL;
|
||||
const char *dname;
|
||||
long offset = 0;
|
||||
pstring destname;
|
||||
|
||||
if (strequal(mask,"????????.???"))
|
||||
pstrcpy(mask,"*");
|
||||
|
||||
if (check_name(directory,conn))
|
||||
dir_hnd = OpenDir(conn, directory, mask, attrs);
|
||||
status = check_name(conn, directory);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
dir_hnd = OpenDir(conn, directory, mask, attrs);
|
||||
if (dir_hnd == NULL) {
|
||||
return map_nt_error_from_unix(errno);
|
||||
}
|
||||
|
||||
if (dir_hnd) {
|
||||
long offset = 0;
|
||||
status = NT_STATUS_NO_SUCH_FILE;
|
||||
/* Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
|
||||
status = NT_STATUS_NO_SUCH_FILE;
|
||||
/* Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
|
||||
|
||||
while ((dname = ReadDirName(dir_hnd, &offset))) {
|
||||
pstring fname;
|
||||
BOOL sysdir_entry = False;
|
||||
while ((dname = ReadDirName(dir_hnd, &offset))) {
|
||||
pstring fname;
|
||||
BOOL sysdir_entry = False;
|
||||
|
||||
pstrcpy(fname,dname);
|
||||
pstrcpy(fname,dname);
|
||||
|
||||
/* Quick check for "." and ".." */
|
||||
if (fname[0] == '.') {
|
||||
if (!fname[1] || (fname[1] == '.' && !fname[2])) {
|
||||
if (attrs & aDIR) {
|
||||
sysdir_entry = True;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
/* Quick check for "." and ".." */
|
||||
if (fname[0] == '.') {
|
||||
if (!fname[1] || (fname[1] == '.' && !fname[2])) {
|
||||
if (attrs & aDIR) {
|
||||
sysdir_entry = True;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_visible_file(conn, directory, dname, &sbuf1, False))
|
||||
continue;
|
||||
|
||||
if(!mask_match(fname, mask, conn->case_sensitive))
|
||||
continue;
|
||||
|
||||
if (sysdir_entry) {
|
||||
status = NT_STATUS_OBJECT_NAME_INVALID;
|
||||
break;
|
||||
}
|
||||
|
||||
status = NT_STATUS_ACCESS_DENIED;
|
||||
slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
|
||||
if (!vfs_object_exist(conn, fname, &sbuf1)) {
|
||||
status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(status)));
|
||||
continue;
|
||||
}
|
||||
status = can_rename(conn,fname,attrs,&sbuf1);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(6,("rename %s refused\n", fname));
|
||||
continue;
|
||||
}
|
||||
pstrcpy(destname,newname);
|
||||
|
||||
if (!resolve_wildcards(fname,destname)) {
|
||||
DEBUG(6,("resolve_wildcards %s %s failed\n",
|
||||
fname, destname));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcsequal(fname,destname)) {
|
||||
rename_open_files(conn, NULL, sbuf1.st_dev, sbuf1.st_ino, newname);
|
||||
DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
|
||||
count++;
|
||||
status = NT_STATUS_OK;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!replace_if_exists &&
|
||||
vfs_file_exist(conn,destname, NULL)) {
|
||||
DEBUG(6,("file_exist %s\n", destname));
|
||||
status = NT_STATUS_OBJECT_NAME_COLLISION;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rename_path_prefix_equal(fname, destname)) {
|
||||
return NT_STATUS_SHARING_VIOLATION;
|
||||
}
|
||||
|
||||
lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino, NULL, NULL);
|
||||
|
||||
if (!SMB_VFS_RENAME(conn,fname,destname)) {
|
||||
rename_open_files(conn, lck, sbuf1.st_dev, sbuf1.st_ino, newname);
|
||||
count++;
|
||||
status = NT_STATUS_OK;
|
||||
}
|
||||
TALLOC_FREE(lck);
|
||||
DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
|
||||
}
|
||||
CloseDir(dir_hnd);
|
||||
|
||||
if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!mask_match(fname, mask, conn->case_sensitive)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sysdir_entry) {
|
||||
status = NT_STATUS_OBJECT_NAME_INVALID;
|
||||
break;
|
||||
}
|
||||
|
||||
status = NT_STATUS_ACCESS_DENIED;
|
||||
slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
|
||||
if (!vfs_object_exist(conn, fname, &sbuf1)) {
|
||||
status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(status)));
|
||||
continue;
|
||||
}
|
||||
status = can_rename(conn,fname,attrs,&sbuf1);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(6,("rename %s refused\n", fname));
|
||||
continue;
|
||||
}
|
||||
pstrcpy(destname,newname);
|
||||
|
||||
if (!resolve_wildcards(fname,destname)) {
|
||||
DEBUG(6,("resolve_wildcards %s %s failed\n",
|
||||
fname, destname));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcsequal(fname,destname)) {
|
||||
rename_open_files(conn, NULL, sbuf1.st_dev, sbuf1.st_ino, newname);
|
||||
DEBUG(3,("rename_internals: identical names in wildcard rename %s - success\n", fname));
|
||||
count++;
|
||||
status = NT_STATUS_OK;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!replace_if_exists && vfs_file_exist(conn,destname, NULL)) {
|
||||
DEBUG(6,("file_exist %s\n", destname));
|
||||
status = NT_STATUS_OBJECT_NAME_COLLISION;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rename_path_prefix_equal(fname, destname)) {
|
||||
return NT_STATUS_SHARING_VIOLATION;
|
||||
}
|
||||
|
||||
lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino, NULL, NULL);
|
||||
|
||||
if (!SMB_VFS_RENAME(conn,fname,destname)) {
|
||||
rename_open_files(conn, lck, sbuf1.st_dev, sbuf1.st_ino, newname);
|
||||
count++;
|
||||
status = NT_STATUS_OK;
|
||||
}
|
||||
TALLOC_FREE(lck);
|
||||
DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
|
||||
}
|
||||
CloseDir(dir_hnd);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Don't think needed any more - JRA. */
|
||||
@ -4386,8 +4414,6 @@ directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
if (count == 0 && NT_STATUS_IS_OK(status)) {
|
||||
status = map_nt_error_from_unix(errno);
|
||||
}
|
||||
@ -4693,40 +4719,49 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
|
||||
} else {
|
||||
struct smb_Dir *dir_hnd = NULL;
|
||||
const char *dname;
|
||||
long offset = 0;
|
||||
pstring destname;
|
||||
|
||||
if (strequal(mask,"????????.???"))
|
||||
pstrcpy(mask,"*");
|
||||
|
||||
if (check_name(directory,conn))
|
||||
dir_hnd = OpenDir(conn, directory, mask, 0);
|
||||
|
||||
if (dir_hnd) {
|
||||
long offset = 0;
|
||||
error = ERRbadfile;
|
||||
|
||||
while ((dname = ReadDirName(dir_hnd, &offset))) {
|
||||
pstring fname;
|
||||
pstrcpy(fname,dname);
|
||||
|
||||
if (!is_visible_file(conn, directory, dname, &sbuf1, False))
|
||||
continue;
|
||||
|
||||
if(!mask_match(fname, mask, conn->case_sensitive))
|
||||
continue;
|
||||
|
||||
error = ERRnoaccess;
|
||||
slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
|
||||
pstrcpy(destname,newname);
|
||||
if (resolve_wildcards(fname,destname)
|
||||
&& NT_STATUS_IS_OK(status = copy_file(
|
||||
fname,destname,conn,ofun,
|
||||
count,target_is_directory)))
|
||||
count++;
|
||||
DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
|
||||
}
|
||||
CloseDir(dir_hnd);
|
||||
status = check_name(conn, directory);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return ERROR_NT(status);
|
||||
}
|
||||
|
||||
dir_hnd = OpenDir(conn, directory, mask, 0);
|
||||
if (dir_hnd == NULL) {
|
||||
status = map_nt_error_from_unix(errno);
|
||||
return ERROR_NT(status);
|
||||
}
|
||||
|
||||
error = ERRbadfile;
|
||||
|
||||
while ((dname = ReadDirName(dir_hnd, &offset))) {
|
||||
pstring fname;
|
||||
pstrcpy(fname,dname);
|
||||
|
||||
if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!mask_match(fname, mask, conn->case_sensitive)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
error = ERRnoaccess;
|
||||
slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
|
||||
pstrcpy(destname,newname);
|
||||
if (resolve_wildcards(fname,destname) &&
|
||||
NT_STATUS_IS_OK(status = copy_file(
|
||||
fname,destname,conn,ofun,
|
||||
count,target_is_directory))) {
|
||||
count++;
|
||||
}
|
||||
DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
|
||||
}
|
||||
CloseDir(dir_hnd);
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
|
@ -805,8 +805,9 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i
|
||||
return ERROR_NT(status);
|
||||
}
|
||||
|
||||
if (!check_name(fname,conn)) {
|
||||
return UNIXERROR(ERRDOS,ERRnoaccess);
|
||||
status = check_name(conn, fname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return ERROR_NT(status);
|
||||
}
|
||||
|
||||
if (open_ofun == 0) {
|
||||
@ -1722,8 +1723,9 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
|
||||
if (!NT_STATUS_IS_OK(ntstatus)) {
|
||||
return ERROR_NT(ntstatus);
|
||||
}
|
||||
if(!check_name(directory,conn)) {
|
||||
return UNIXERROR(ERRDOS,ERRbadpath);
|
||||
ntstatus = check_name(conn, directory);
|
||||
if (!NT_STATUS_IS_OK(ntstatus)) {
|
||||
return ERROR_NT(ntstatus);
|
||||
}
|
||||
|
||||
p = strrchr_m(directory,'/');
|
||||
@ -1764,7 +1766,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
|
||||
if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
|
||||
return ERROR_NT(NT_STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
|
||||
/* Pull out the list of names. */
|
||||
ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
|
||||
if (!ea_list) {
|
||||
@ -1792,10 +1794,10 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
|
||||
/* Save the wildcard match and attribs we are using on this directory -
|
||||
needed as lanman2 assumes these are being saved between calls */
|
||||
|
||||
dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype);
|
||||
if (dptr_num < 0) {
|
||||
ntstatus = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype, &dptr_num);
|
||||
if (!NT_STATUS_IS_OK(ntstatus)) {
|
||||
talloc_destroy(ea_ctx);
|
||||
return(UNIXERROR(ERRDOS,ERRbadfile));
|
||||
return ERROR_NT(ntstatus);
|
||||
}
|
||||
|
||||
DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
|
||||
@ -2934,9 +2936,10 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return ERROR_NT(status);
|
||||
}
|
||||
if (!check_name(fname,conn)) {
|
||||
DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
|
||||
return UNIXERROR(ERRDOS,ERRbadpath);
|
||||
status = check_name(conn, fname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
|
||||
return ERROR_NT(status);
|
||||
}
|
||||
|
||||
if (INFO_LEVEL_IS_UNIX(info_level)) {
|
||||
@ -3686,7 +3689,8 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newnam
|
||||
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
if (!check_name(oldname,conn)) {
|
||||
status = check_name(conn, oldname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
@ -3700,7 +3704,8 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newnam
|
||||
return NT_STATUS_OBJECT_NAME_COLLISION;
|
||||
}
|
||||
|
||||
if (!check_name(newname,conn)) {
|
||||
status = check_name(conn, newname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
@ -3710,8 +3715,10 @@ NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newnam
|
||||
}
|
||||
|
||||
/* Ensure this is within the share. */
|
||||
if (!reduce_name(conn, oldname) != 0)
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
status = reduce_name(conn, oldname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
|
||||
|
||||
@ -3826,8 +3833,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
|
||||
return UNIXERROR(ERRDOS,ERRbadpath);
|
||||
}
|
||||
|
||||
if(!check_name(fname, conn)) {
|
||||
return UNIXERROR(ERRDOS,ERRbadpath);
|
||||
status = check_name(conn, fname);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return ERROR_NT(status);
|
||||
}
|
||||
|
||||
}
|
||||
@ -4366,8 +4374,9 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
|
||||
}
|
||||
pstrcat(rel_name, link_target);
|
||||
|
||||
if (!check_name(rel_name, conn)) {
|
||||
return(UNIXERROR(ERRDOS,ERRnoaccess));
|
||||
status = check_name(conn, rel_name);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return ERROR_NT(status);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4823,9 +4832,10 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf,
|
||||
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
if (!check_name(directory,conn)) {
|
||||
DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
|
||||
return UNIXERROR(ERRDOS, ERRnoaccess);
|
||||
status = check_name(conn, directory);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
|
||||
return ERROR_NT(status);
|
||||
}
|
||||
|
||||
status = create_directory(conn, directory);
|
||||
|
@ -821,7 +821,7 @@ BOOL canonicalize_path(connection_struct *conn, pstring path)
|
||||
it is below dir in the heirachy. This uses realpath.
|
||||
********************************************************************/
|
||||
|
||||
BOOL reduce_name(connection_struct *conn, const pstring fname)
|
||||
NTSTATUS reduce_name(connection_struct *conn, const pstring fname)
|
||||
{
|
||||
#ifdef REALPATH_TAKES_NULL
|
||||
BOOL free_resolved_name = True;
|
||||
@ -836,7 +836,6 @@ BOOL reduce_name(connection_struct *conn, const pstring fname)
|
||||
char *resolved_name = NULL;
|
||||
size_t con_path_len = strlen(conn->connectpath);
|
||||
char *p = NULL;
|
||||
int saved_errno = errno;
|
||||
|
||||
DEBUG(3,("reduce_name [%s] [%s]\n", fname, conn->connectpath));
|
||||
|
||||
@ -850,8 +849,7 @@ BOOL reduce_name(connection_struct *conn, const pstring fname)
|
||||
switch (errno) {
|
||||
case ENOTDIR:
|
||||
DEBUG(3,("reduce_name: Component not a directory in getting realpath for %s\n", fname));
|
||||
errno = saved_errno;
|
||||
return False;
|
||||
return map_nt_error_from_unix(errno);
|
||||
case ENOENT:
|
||||
{
|
||||
pstring tmp_fname;
|
||||
@ -875,8 +873,7 @@ BOOL reduce_name(connection_struct *conn, const pstring fname)
|
||||
#endif
|
||||
if (!resolved_name) {
|
||||
DEBUG(3,("reduce_name: couldn't get realpath for %s\n", fname));
|
||||
errno = saved_errno;
|
||||
return False;
|
||||
return map_nt_error_from_unix(errno);
|
||||
}
|
||||
pstrcpy(tmp_fname, resolved_name);
|
||||
pstrcat(tmp_fname, "/");
|
||||
@ -886,8 +883,7 @@ BOOL reduce_name(connection_struct *conn, const pstring fname)
|
||||
resolved_name = SMB_STRDUP(tmp_fname);
|
||||
if (!resolved_name) {
|
||||
DEBUG(0,("reduce_name: malloc fail for %s\n", tmp_fname));
|
||||
errno = saved_errno;
|
||||
return False;
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
#else
|
||||
#ifdef PATH_MAX
|
||||
@ -901,9 +897,7 @@ BOOL reduce_name(connection_struct *conn, const pstring fname)
|
||||
}
|
||||
default:
|
||||
DEBUG(1,("reduce_name: couldn't get realpath for %s\n", fname));
|
||||
/* Don't restore the saved errno. We need to return the error that
|
||||
realpath caused here as it was not one of the cases we handle. JRA. */
|
||||
return False;
|
||||
return map_nt_error_from_unix(errno);
|
||||
}
|
||||
}
|
||||
|
||||
@ -911,19 +905,19 @@ BOOL reduce_name(connection_struct *conn, const pstring fname)
|
||||
|
||||
if (*resolved_name != '/') {
|
||||
DEBUG(0,("reduce_name: realpath doesn't return absolute paths !\n"));
|
||||
if (free_resolved_name)
|
||||
if (free_resolved_name) {
|
||||
SAFE_FREE(resolved_name);
|
||||
errno = saved_errno;
|
||||
return False;
|
||||
}
|
||||
return NT_STATUS_OBJECT_NAME_INVALID;
|
||||
}
|
||||
|
||||
/* Check for widelinks allowed. */
|
||||
if (!lp_widelinks(SNUM(conn)) && (strncmp(conn->connectpath, resolved_name, con_path_len) != 0)) {
|
||||
DEBUG(2, ("reduce_name: Bad access attempt: %s is a symlink outside the share path", fname));
|
||||
if (free_resolved_name)
|
||||
if (free_resolved_name) {
|
||||
SAFE_FREE(resolved_name);
|
||||
errno = EACCES;
|
||||
return False;
|
||||
}
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
/* Check if we are allowing users to follow symlinks */
|
||||
@ -935,18 +929,18 @@ BOOL reduce_name(connection_struct *conn, const pstring fname)
|
||||
SMB_STRUCT_STAT statbuf;
|
||||
if ( (SMB_VFS_LSTAT(conn,fname,&statbuf) != -1) &&
|
||||
(S_ISLNK(statbuf.st_mode)) ) {
|
||||
if (free_resolved_name)
|
||||
if (free_resolved_name) {
|
||||
SAFE_FREE(resolved_name);
|
||||
}
|
||||
DEBUG(3,("reduce_name: denied: file path name %s is a symlink\n",resolved_name));
|
||||
errno = EACCES;
|
||||
return False;
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
DEBUG(3,("reduce_name: %s reduced to %s\n", fname, resolved_name));
|
||||
if (free_resolved_name)
|
||||
if (free_resolved_name) {
|
||||
SAFE_FREE(resolved_name);
|
||||
errno = saved_errno;
|
||||
return(True);
|
||||
}
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user