diff --git a/source/smbd/filename.c b/source/smbd/filename.c index d240ecf..003cb0f 100644 --- a/source/smbd/filename.c +++ b/source/smbd/filename.c @@ -126,7 +126,9 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, char *stream = NULL; bool component_was_mangled = False; bool name_has_wildcard = False; + bool posix_pathnames = false; NTSTATUS result; + int ret = -1; SET_STAT_INVALID(*pst); *pp_conv_path = NULL; @@ -225,7 +227,9 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, } } - if (!lp_posix_pathnames()) { + posix_pathnames = lp_posix_pathnames(); + + if (!posix_pathnames) { stream = strchr_m(name, ':'); if (stream != NULL) { @@ -268,7 +272,13 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, * stat the name - if it exists then we are all done! */ - if (SMB_VFS_STAT(conn,name,&st) == 0) { + if (posix_pathnames) { + ret = SMB_VFS_LSTAT(conn,name,&st); + } else { + ret = SMB_VFS_STAT(conn,name,&st); + } + + if (ret == 0) { /* Ensure we catch all names with in "/." this is disallowed under Windows. */ const char *p = strstr(name, "/."); /* mb safe. */ @@ -380,7 +390,13 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, * Check if the name exists up to this point. */ - if (SMB_VFS_STAT(conn,name, &st) == 0) { + if (posix_pathnames) { + ret = SMB_VFS_LSTAT(conn,name, &st); + } else { + ret = SMB_VFS_STAT(conn,name, &st); + } + + if (ret == 0) { /* * It exists. it must either be a directory or this must * be the last part of the path for it to be OK. @@ -598,7 +614,13 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, * if it exists. JRA. */ - if (SMB_VFS_STAT(conn,name, &st) == 0) { + if (posix_pathnames) { + ret = SMB_VFS_LSTAT(conn,name, &st); + } else { + ret = SMB_VFS_STAT(conn,name, &st); + } + + if (ret == 0) { *pst = st; } else { SET_STAT_INVALID(st); diff --git a/source/smbd/open.c b/source/smbd/open.c index 7e127ea..716b9ff 100644 --- a/source/smbd/open.c +++ b/source/smbd/open.c @@ -415,28 +415,42 @@ static NTSTATUS open_file(files_struct *fsp, access_mask, &access_granted); if (!NT_STATUS_IS_OK(status)) { - - /* Were we trying to do a stat open - * for delete and didn't get DELETE - * access (only) ? Check if the - * directory allows DELETE_CHILD. - * See here: - * http://blogs.msdn.com/oldnewthing/archive/2004/06/04/148426.aspx - * for details. */ - - if (!(NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) && - (access_mask & DELETE_ACCESS) && - (access_granted == DELETE_ACCESS) && - can_delete_file_in_directory(conn, path))) { - DEBUG(10, ("open_file: Access denied on " - "file %s\n", - path)); + if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) { + if ((access_mask & DELETE_ACCESS) && + (access_granted == DELETE_ACCESS) && + can_delete_file_in_directory(conn, path)) { + /* Were we trying to do a stat open + * for delete and didn't get DELETE + * access (only) ? Check if the + * directory allows DELETE_CHILD. + * See here: + * http://blogs.msdn.com/oldnewthing/archive/2004/06/04/148426.aspx + * for details. */ + + DEBUG(10,("open_file: overrode ACCESS_DENIED " + "on file %s\n", + path )); + } else { + DEBUG(10, ("open_file: Access denied on " + "file %s\n", + path)); + return status; + } + } else if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) && + fsp->posix_open && + S_ISLNK(psbuf->st_mode)) { + /* This is a POSIX stat open for delete + * or rename on a symlink that points + * nowhere. Allow. */ + DEBUG(10, ("open_file: allowing POSIX open " + "on bad symlink %s\n", + path )); + } else { + DEBUG(10, ("open_file: check_open_rights " + "on file %s returned %s\n", + path, nt_errstr(status) )); return status; } - - DEBUG(10,("open_file: overrode ACCESS_DENIED " - "on file %s\n", - path )); } } } diff --git a/source/smbd/reply.c b/source/smbd/reply.c index c192d4a..8e757da 100644 --- a/source/smbd/reply.c +++ b/source/smbd/reply.c @@ -5614,7 +5614,13 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, return map_nt_error_from_unix(errno); } } else { - if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) { + int ret = -1; + if (fsp->posix_open) { + ret = SMB_VFS_LSTAT(conn,fsp->fsp_name,&sbuf); + } else { + ret = SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf); + } + if (ret == -1) { return map_nt_error_from_unix(errno); } } @@ -5718,6 +5724,7 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, struct smb_Dir *dir_hnd = NULL; const char *dname; long offset = 0; + bool posix_pathnames = lp_posix_pathnames(); ZERO_STRUCT(sbuf1); ZERO_STRUCT(sbuf2); @@ -5829,19 +5836,30 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, } ZERO_STRUCT(sbuf1); - SMB_VFS_STAT(conn, directory, &sbuf1); + if (posix_pathnames) { + SMB_VFS_LSTAT(conn, directory, &sbuf1); + } else { + SMB_VFS_STAT(conn, directory, &sbuf1); + } status = S_ISDIR(sbuf1.st_mode) ? open_directory(conn, req, directory, &sbuf1, - access_mask, - FILE_SHARE_READ|FILE_SHARE_WRITE, - FILE_OPEN, 0, 0, NULL, - &fsp) + access_mask, + FILE_SHARE_READ|FILE_SHARE_WRITE, + FILE_OPEN, + 0, + posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, + NULL, + &fsp) : open_file_ntcreate(conn, req, directory, &sbuf1, - access_mask, - FILE_SHARE_READ|FILE_SHARE_WRITE, - FILE_OPEN, 0, 0, 0, NULL, - &fsp); + access_mask, + FILE_SHARE_READ|FILE_SHARE_WRITE, + FILE_OPEN, + 0, + posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, + 0, + NULL, + &fsp); if (!NT_STATUS_IS_OK(status)) { DEBUG(3, ("Could not open rename source %s: %s\n", @@ -5933,19 +5951,30 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx, } ZERO_STRUCT(sbuf1); - SMB_VFS_STAT(conn, fname, &sbuf1); + if (posix_pathnames) { + SMB_VFS_LSTAT(conn, fname, &sbuf1); + } else { + SMB_VFS_STAT(conn, fname, &sbuf1); + } status = S_ISDIR(sbuf1.st_mode) ? open_directory(conn, req, fname, &sbuf1, - access_mask, - FILE_SHARE_READ|FILE_SHARE_WRITE, - FILE_OPEN, 0, 0, NULL, - &fsp) + access_mask, + FILE_SHARE_READ|FILE_SHARE_WRITE, + FILE_OPEN, + 0, + posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, + NULL, + &fsp) : open_file_ntcreate(conn, req, fname, &sbuf1, - access_mask, - FILE_SHARE_READ|FILE_SHARE_WRITE, - FILE_OPEN, 0, 0, 0, NULL, - &fsp); + access_mask, + FILE_SHARE_READ|FILE_SHARE_WRITE, + FILE_OPEN, + 0, + posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, + 0, + NULL, + &fsp); if (!NT_STATUS_IS_OK(status)) { DEBUG(3,("rename_internals: open_file_ntcreate " @@ -7123,7 +7152,14 @@ void reply_setattrE(struct smb_request *req) return; } } else { - if (SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf) == -1) { + int ret = -1; + + if (fsp->posix_open) { + ret = SMB_VFS_LSTAT(conn, fsp->fsp_name, &sbuf); + } else { + ret = SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf); + } + if (ret == -1) { status = map_nt_error_from_unix(errno); reply_nterror(req, status); END_PROFILE(SMBsetattrE);