summaryrefslogtreecommitdiff
path: root/source3/smbd/open.c
diff options
context:
space:
mode:
authorJelmer Vernooij <jelmer@samba.org>2009-02-05 16:39:28 +0100
committerJelmer Vernooij <jelmer@samba.org>2009-02-05 16:39:28 +0100
commit6d139ca4680abcbda5110f2f0886aa038ff62088 (patch)
tree7d61db40fb058bcbf08ccd8e0dadc365b819371b /source3/smbd/open.c
parent4a9b3052caeb8bb144803b49dcfae82395172bc3 (diff)
parentafa960cbbcd609123d710c301e7a9a070c1fed70 (diff)
downloadsamba-6d139ca4680abcbda5110f2f0886aa038ff62088.tar.gz
samba-6d139ca4680abcbda5110f2f0886aa038ff62088.tar.bz2
samba-6d139ca4680abcbda5110f2f0886aa038ff62088.zip
Merge branch 'master' of ssh://git.samba.org/data/git/samba
Conflicts: librpc/ndr.pc.in
Diffstat (limited to 'source3/smbd/open.c')
-rw-r--r--source3/smbd/open.c70
1 files changed, 60 insertions, 10 deletions
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 7d23b92359..f7a52d7bd2 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -67,13 +67,15 @@ NTSTATUS smb1_file_se_access_check(const struct security_descriptor *sd,
static NTSTATUS check_open_rights(struct connection_struct *conn,
const char *fname,
- uint32_t access_mask)
+ uint32_t access_mask,
+ uint32_t *access_granted)
{
/* Check if we have rights to open. */
NTSTATUS status;
- uint32_t access_granted = 0;
struct security_descriptor *sd;
+ *access_granted = 0;
+
status = SMB_VFS_GET_NT_ACL(conn, fname,
(OWNER_SECURITY_INFORMATION |
GROUP_SECURITY_INFORMATION |
@@ -90,9 +92,17 @@ static NTSTATUS check_open_rights(struct connection_struct *conn,
status = smb1_file_se_access_check(sd,
conn->server_info->ptok,
access_mask,
- &access_granted);
+ access_granted);
TALLOC_FREE(sd);
+
+ DEBUG(10,("check_open_rights: file %s requesting "
+ "0x%x returning 0x%x (%s)\n",
+ fname,
+ (unsigned int)access_mask,
+ (unsigned int)*access_granted,
+ nt_errstr(status) ));
+
return status;
}
@@ -415,14 +425,49 @@ static NTSTATUS open_file(files_struct *fsp,
} else {
fsp->fh->fd = -1; /* What we used to call a stat open. */
if (file_existed) {
+ uint32_t access_granted = 0;
+
status = check_open_rights(conn,
path,
- access_mask);
+ access_mask,
+ &access_granted);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(10, ("open_file: Access denied on "
- "file %s\n",
- path));
- return status;
+ 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;
+ }
}
}
}
@@ -2395,9 +2440,11 @@ static NTSTATUS open_directory(connection_struct *conn,
}
if (info == FILE_WAS_OPENED) {
+ uint32_t access_granted = 0;
status = check_open_rights(conn,
fname,
- access_mask);
+ access_mask,
+ &access_granted);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10, ("open_directory: check_open_rights on "
"file %s failed with %s\n",
@@ -2826,8 +2873,11 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
&& (create_disposition != FILE_CREATE)
&& (share_access & FILE_SHARE_DELETE)
&& (access_mask & DELETE_ACCESS)
- && (!can_delete_file_in_directory(conn, fname))) {
+ && (!(can_delete_file_in_directory(conn, fname) ||
+ can_access_file_acl(conn, fname, DELETE_ACCESS)))) {
status = NT_STATUS_ACCESS_DENIED;
+ DEBUG(10,("create_file_unixpath: open file %s "
+ "for delete ACCESS_DENIED\n", fname ));
goto fail;
}