The branch, master has been updated via f30f71c Fix bug #8548 - winbind_samlogon_retry_loop ignores logon_parameters flags. via 8c6ff21 The xcopy test is used in unusual ways (via a different uid). Ensure we can cope with this. via 3bd6513 Remove the order dependency in parent_override_delete(), just check for & not ==. via 80c3aa7 The xcopy test requires "dos filemode=yes" as it opens with WRITE_OWNER. via 30a5996 Remove the mkdir and open functions from the ACL modules - main code paths now handle this. via 8a65e2c Remove unused "struct security_descriptor" parameter from check_parent_access() via ea195b6 Finally do all the open checks inside open_file(). Checks inside vfs_acl_common can now be removed. via 8a3070a Simplify smbd_check_open_rights() and move all the special casing inside it. via 18df3ae Move parent_override_delete() to before I need to use it. via 1619de3 Make smbd_check_open_rights() static. from 151bb29 s3-net: Make sure to always re-use the "good" dc for the DNS updates as well.
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit f30f71c14a0b89dea296910ac9b92d3ae4016613 Author: Jeremy Allison <j...@samba.org> Date: Fri Oct 28 12:29:54 2011 -0700 Fix bug #8548 - winbind_samlogon_retry_loop ignores logon_parameters flags. Fix confirmed by reporter. Autobuild-User: Jeremy Allison <j...@samba.org> Autobuild-Date: Fri Oct 28 23:04:47 CEST 2011 on sn-devel-104 commit 8c6ff21782b141571dde64e80cc42540e9177a23 Author: Jeremy Allison <j...@samba.org> Date: Fri Oct 28 12:15:51 2011 -0700 The xcopy test is used in unusual ways (via a different uid). Ensure we can cope with this. commit 3bd6513884f1f02fe5638a424bcb1948f0921853 Author: Jeremy Allison <j...@samba.org> Date: Thu Oct 27 16:48:13 2011 -0700 Remove the order dependency in parent_override_delete(), just check for & not ==. commit 80c3aa7d2991302a2280dbfe6df14040347fdc52 Author: Jeremy Allison <j...@samba.org> Date: Thu Oct 27 16:41:18 2011 -0700 The xcopy test requires "dos filemode=yes" as it opens with WRITE_OWNER. commit 30a599684a0a8c1f9af2d5b8adf8302172b49ae3 Author: Jeremy Allison <j...@samba.org> Date: Wed Oct 26 16:02:40 2011 -0700 Remove the mkdir and open functions from the ACL modules - main code paths now handle this. commit 8a65e2c747c17be023d8c1285e0c8b2394fd4354 Author: Jeremy Allison <j...@samba.org> Date: Wed Oct 26 15:30:00 2011 -0700 Remove unused "struct security_descriptor" parameter from check_parent_access() commit ea195b6cd2152a7f09847dba9c0c2288cc9a862d Author: Jeremy Allison <j...@samba.org> Date: Wed Oct 26 15:03:28 2011 -0700 Finally do all the open checks inside open_file(). Checks inside vfs_acl_common can now be removed. commit 8a3070a7c9fe3fad35103435c5c74188866057eb Author: Jeremy Allison <j...@samba.org> Date: Wed Oct 26 14:58:32 2011 -0700 Simplify smbd_check_open_rights() and move all the special casing inside it. commit 18df3aedb9dc0b7af0cc4046efb23026708f5d71 Author: Jeremy Allison <j...@samba.org> Date: Wed Oct 26 14:47:52 2011 -0700 Move parent_override_delete() to before I need to use it. commit 1619de30805e57adc8bf063a9ccf6f5ba245bc5a Author: Jeremy Allison <j...@samba.org> Date: Wed Oct 26 14:06:41 2011 -0700 Make smbd_check_open_rights() static. ----------------------------------------------------------------------- Summary of changes: selftest/target/Samba3.pm | 6 + selftest/target/Samba4.pm | 7 + source3/modules/vfs_acl_common.c | 140 +-------------------- source3/modules/vfs_acl_tdb.c | 2 - source3/modules/vfs_acl_xattr.c | 2 - source3/smbd/globals.h | 4 - source3/smbd/open.c | 251 +++++++++++++++++++------------------- source3/winbindd/winbindd_pam.c | 4 +- source4/selftest/tests.py | 18 ++-- 9 files changed, 153 insertions(+), 281 deletions(-) Changeset truncated at 500 lines: diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm index 2f23ae3..3c0fbe9 100755 --- a/selftest/target/Samba3.pm +++ b/selftest/target/Samba3.pm @@ -916,6 +916,7 @@ sub provision($$$$$$$) map readonly = no store dos attributes = yes create mask = 755 + dos filemode = yes vfs objects = $vfs_modulesdir_abs/xattr_tdb.so $vfs_modulesdir_abs/streams_depot.so printing = vlp @@ -1002,6 +1003,11 @@ sub provision($$$$$$$) copy = print1 [lp] copy = print1 +[xcopy_share] + path = $shrdir + comment = smb username is [%U] + create mask = 777 + force create mode = 777 [print\$] copy = tmp "; diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm index 6d67229..506bbee 100644 --- a/selftest/target/Samba4.pm +++ b/selftest/target/Samba4.pm @@ -751,6 +751,13 @@ sub provision($$$$$$$$$) posix:oplocktimeout = 3 posix:writetimeupdatedelay = 500000 +[xcopy_share] + path = $ctx->{tmpdir} + read only = no + posix:sharedelay = 10000 + posix:oplocktimeout = 3 + posix:writetimeupdatedelay = 500000 + [test1] path = $ctx->{tmpdir}/test1 read only = no diff --git a/source3/modules/vfs_acl_common.c b/source3/modules/vfs_acl_common.c index 1947a77..14ac6f7 100644 --- a/source3/modules/vfs_acl_common.c +++ b/source3/modules/vfs_acl_common.c @@ -600,124 +600,6 @@ static NTSTATUS check_parent_acl_common(vfs_handle_struct *handle, } /********************************************************************* - Check ACL on open. For new files inherit from parent directory. -*********************************************************************/ - -static int open_acl_common(vfs_handle_struct *handle, - struct smb_filename *smb_fname, - files_struct *fsp, - int flags, - mode_t mode) -{ - uint32_t access_granted = 0; - struct security_descriptor *pdesc = NULL; - bool file_existed = true; - char *fname = NULL; - NTSTATUS status; - - if (fsp->base_fsp) { - /* Stream open. Base filename open already did the ACL check. */ - DEBUG(10,("open_acl_common: stream open on %s\n", - fsp_str_dbg(fsp) )); - return SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode); - } - - status = get_full_smb_filename(talloc_tos(), smb_fname, - &fname); - if (!NT_STATUS_IS_OK(status)) { - goto err; - } - - status = get_nt_acl_internal(handle, - NULL, - fname, - (SECINFO_OWNER | - SECINFO_GROUP | - SECINFO_DACL), - &pdesc); - if (NT_STATUS_IS_OK(status)) { - /* See if we can access it. */ - status = smb1_file_se_access_check(handle->conn, - pdesc, - get_current_nttok(handle->conn), - fsp->access_mask, - &access_granted); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(10,("open_acl_xattr: %s open " - "refused with error %s\n", - fsp_str_dbg(fsp), - nt_errstr(status) )); - goto err; - } - } else if (NT_STATUS_EQUAL(status,NT_STATUS_OBJECT_NAME_NOT_FOUND)) { - file_existed = false; - /* - * If O_CREAT is true then we're trying to create a file. - * Check the parent directory ACL will allow this. - */ - if (flags & O_CREAT) { - struct security_descriptor *parent_desc = NULL; - struct security_descriptor **pp_psd = NULL; - - status = check_parent_acl_common(handle, fname, - SEC_DIR_ADD_FILE, &parent_desc); - if (!NT_STATUS_IS_OK(status)) { - goto err; - } - - /* Cache the parent security descriptor for - * later use. */ - - pp_psd = (struct security_descriptor **) - VFS_ADD_FSP_EXTENSION(handle, - fsp, - struct security_descriptor *, - NULL); - if (!pp_psd) { - status = NT_STATUS_NO_MEMORY; - goto err; - } - - *pp_psd = parent_desc; - status = NT_STATUS_OK; - } - } - - DEBUG(10,("open_acl_xattr: get_nt_acl_attr_internal for " - "%s returned %s\n", - fsp_str_dbg(fsp), - nt_errstr(status) )); - - fsp->fh->fd = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode); - return fsp->fh->fd; - - err: - - errno = map_errno_from_nt_status(status); - return -1; -} - -static int mkdir_acl_common(vfs_handle_struct *handle, const char *path, mode_t mode) -{ - int ret; - NTSTATUS status; - SMB_STRUCT_STAT sbuf; - - ret = vfs_stat_smb_fname(handle->conn, path, &sbuf); - if (ret == -1 && errno == ENOENT) { - /* We're creating a new directory. */ - status = check_parent_acl_common(handle, path, - SEC_DIR_ADD_SUBDIR, NULL); - if (!NT_STATUS_IS_OK(status)) { - errno = map_errno_from_nt_status(status); - return -1; - } - } - - return SMB_VFS_NEXT_MKDIR(handle, path, mode); -} - -/********************************************************************* Fetch a security descriptor given an fsp. *********************************************************************/ @@ -965,7 +847,6 @@ static NTSTATUS create_file_acl_common(struct vfs_handle_struct *handle, files_struct *fsp = NULL; int info; struct security_descriptor *parent_sd = NULL; - struct security_descriptor **pp_parent_sd = NULL; status = SMB_VFS_NEXT_CREATE_FILE(handle, req, @@ -1010,18 +891,11 @@ static NTSTATUS create_file_acl_common(struct vfs_handle_struct *handle, goto out; } - /* See if we have a cached parent sd, if so, use it. */ - pp_parent_sd = (struct security_descriptor **)VFS_FETCH_FSP_EXTENSION(handle, fsp); - if (!pp_parent_sd) { - /* Must be a directory, fetch again (sigh). */ - status = get_parent_acl_common(handle, - fsp->fsp_name->base_name, - &parent_sd); - if (!NT_STATUS_IS_OK(status)) { - goto out; - } - } else { - parent_sd = *pp_parent_sd; + status = get_parent_acl_common(handle, + fsp->fsp_name->base_name, + &parent_sd); + if (!NT_STATUS_IS_OK(status)) { + goto out; } if (!parent_sd) { @@ -1040,9 +914,7 @@ static NTSTATUS create_file_acl_common(struct vfs_handle_struct *handle, out: - if (fsp) { - VFS_REMOVE_FSP_EXTENSION(handle, fsp); - } + TALLOC_FREE(parent_sd); if (NT_STATUS_IS_OK(status) && pinfo) { *pinfo = info; diff --git a/source3/modules/vfs_acl_tdb.c b/source3/modules/vfs_acl_tdb.c index 778e837..a4869c0 100644 --- a/source3/modules/vfs_acl_tdb.c +++ b/source3/modules/vfs_acl_tdb.c @@ -401,9 +401,7 @@ static struct vfs_fn_pointers vfs_acl_tdb_fns = { .connect_fn = connect_acl_tdb, .disconnect = disconnect_acl_tdb, .opendir = opendir_acl_common, - .mkdir = mkdir_acl_common, .rmdir = rmdir_acl_tdb, - .open_fn = open_acl_common, .create_file = create_file_acl_common, .unlink = unlink_acl_tdb, .chmod = chmod_acl_module_common, diff --git a/source3/modules/vfs_acl_xattr.c b/source3/modules/vfs_acl_xattr.c index b522b33..473c2fc 100644 --- a/source3/modules/vfs_acl_xattr.c +++ b/source3/modules/vfs_acl_xattr.c @@ -202,9 +202,7 @@ static int connect_acl_xattr(struct vfs_handle_struct *handle, static struct vfs_fn_pointers vfs_acl_xattr_fns = { .connect_fn = connect_acl_xattr, .opendir = opendir_acl_common, - .mkdir = mkdir_acl_common, .rmdir = rmdir_acl_common, - .open_fn = open_acl_common, .create_file = create_file_acl_common, .unlink = unlink_acl_common, .chmod = chmod_acl_module_common, diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 472aeee..14337e0 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -221,10 +221,6 @@ NTSTATUS smbd_calculate_access_mask(connection_struct *conn, bool file_existed, uint32_t access_mask, uint32_t *access_mask_out); -NTSTATUS smbd_check_open_rights(struct connection_struct *conn, - const struct smb_filename *smb_fname, - uint32_t access_mask, - uint32_t *access_granted); void smbd_notify_cancel_by_smbreq(const struct smb_request *smbreq); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 6ad85b7..42edddc 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -65,33 +65,54 @@ NTSTATUS smb1_file_se_access_check(struct connection_struct *conn, } /**************************************************************************** + If the requester wanted DELETE_ACCESS and was rejected because + the file ACL didn't include DELETE_ACCESS, see if the parent ACL + ovverrides this. +****************************************************************************/ + +static bool parent_override_delete(connection_struct *conn, + struct smb_filename *smb_fname, + uint32_t access_mask, + uint32_t rejected_mask) +{ + if ((access_mask & DELETE_ACCESS) && + (rejected_mask & DELETE_ACCESS) && + can_delete_file_in_directory(conn, smb_fname)) { + return true; + } + return false; +} + +/**************************************************************************** Check if we have open rights. ****************************************************************************/ -NTSTATUS smbd_check_open_rights(struct connection_struct *conn, - const struct smb_filename *smb_fname, - uint32_t access_mask, - uint32_t *access_granted) +static NTSTATUS smbd_check_open_rights(struct connection_struct *conn, + struct smb_filename *smb_fname, + uint32_t access_mask) { /* Check if we have rights to open. */ NTSTATUS status; struct security_descriptor *sd = NULL; uint32_t rejected_share_access; + uint32_t rejected_mask = 0; rejected_share_access = access_mask & ~(conn->share_access); if (rejected_share_access) { - *access_granted = rejected_share_access; + DEBUG(10, ("smbd_check_open_rights: rejected share access 0x%x " + "on %s (0x%x)\n", + (unsigned int)access_mask, + smb_fname_str_dbg(smb_fname), + (unsigned int)rejected_share_access )); return NT_STATUS_ACCESS_DENIED; } if ((access_mask & DELETE_ACCESS) && !lp_acl_check_permissions(SNUM(conn))) { - *access_granted = access_mask; - DEBUG(10,("smbd_check_open_rights: not checking ACL " "on DELETE_ACCESS on file %s. Granting 0x%x\n", smb_fname_str_dbg(smb_fname), - (unsigned int)*access_granted )); + (unsigned int)access_mask )); return NT_STATUS_OK; } @@ -112,13 +133,13 @@ NTSTATUS smbd_check_open_rights(struct connection_struct *conn, sd, get_current_nttok(conn), access_mask, - access_granted); + &rejected_mask); DEBUG(10,("smbd_check_open_rights: file %s requesting " "0x%x returning 0x%x (%s)\n", smb_fname_str_dbg(smb_fname), (unsigned int)access_mask, - (unsigned int)*access_granted, + (unsigned int)rejected_mask, nt_errstr(status) )); if (!NT_STATUS_IS_OK(status)) { @@ -131,14 +152,59 @@ NTSTATUS smbd_check_open_rights(struct connection_struct *conn, TALLOC_FREE(sd); - return status; + if (NT_STATUS_IS_OK(status) || + !NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) { + return status; + } + + /* Here we know status == NT_STATUS_ACCESS_DENIED. */ + if ((access_mask & FILE_WRITE_ATTRIBUTES) && + (rejected_mask & FILE_WRITE_ATTRIBUTES) && + (lp_map_readonly(SNUM(conn)) || + lp_map_archive(SNUM(conn)) || + lp_map_hidden(SNUM(conn)) || + lp_map_system(SNUM(conn)))) { + rejected_mask &= ~FILE_WRITE_ATTRIBUTES; + + DEBUG(10,("smbd_check_open_rights: " + "overrode " + "FILE_WRITE_ATTRIBUTES " + "on file %s\n", + smb_fname_str_dbg(smb_fname))); + } + + if (parent_override_delete(conn, + smb_fname, + access_mask, + rejected_mask)) { + /* Were we trying to do an 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. */ + + rejected_mask &= ~DELETE_ACCESS; + + DEBUG(10,("smbd_check_open_rights: " + "overrode " + "DELETE_ACCESS on " + "file %s\n", + smb_fname_str_dbg(smb_fname))); + } + + if (rejected_mask != 0) { + return NT_STATUS_ACCESS_DENIED; + } else { + return NT_STATUS_OK; + } } static NTSTATUS check_parent_access(struct connection_struct *conn, struct smb_filename *smb_fname, uint32_t access_mask, - char **pp_parent_dir, - struct security_descriptor **pp_parent_sd) + char **pp_parent_dir) { NTSTATUS status; char *parent_dir = NULL; @@ -185,32 +251,10 @@ static NTSTATUS check_parent_access(struct connection_struct *conn, if (pp_parent_dir) { *pp_parent_dir = parent_dir; } - if (pp_parent_sd) { - *pp_parent_sd = parent_sd; - } return NT_STATUS_OK; } /**************************************************************************** - If the requester wanted DELETE_ACCESS and was only rejected because - the file ACL didn't include DELETE_ACCESS, see if the parent ACL - ovverrides this. -****************************************************************************/ - -static bool parent_override_delete(connection_struct *conn, - struct smb_filename *smb_fname, - uint32_t access_mask, - uint32_t rejected_mask) -{ - if ((access_mask & DELETE_ACCESS) && - (rejected_mask == DELETE_ACCESS) && - can_delete_file_in_directory(conn, smb_fname)) { - return true; - } - return false; -} - -/**************************************************************************** fd support routines - attempt to do a dos_open. ****************************************************************************/ @@ -565,6 +609,35 @@ static NTSTATUS open_file(files_struct *fsp, return NT_STATUS_OBJECT_NAME_INVALID; } + /* Can we access this file ? */ + if (!fsp->base_fsp) { + /* Only do this check on non-stream open. */ + if (file_existed) { + status = smbd_check_open_rights(conn, + smb_fname, + access_mask); + } else if (local_flags & O_CREAT){ + status = check_parent_access(conn, + smb_fname, + SEC_DIR_ADD_FILE, + NULL); + } else { + /* File didn't exist and no O_CREAT. */ + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10,("open_file: " + "%s on file " + "%s returned %s\n", + file_existed ? + "smbd_check_open_rights" : + "check_parent_access", + smb_fname_str_dbg(smb_fname), + nt_errstr(status) )); + return status; + } + } + /* Actually do the open */ status = fd_open(conn, fsp, local_flags, unx_mode); if (!NT_STATUS_IS_OK(status)) { @@ -579,8 +652,6 @@ static NTSTATUS open_file(files_struct *fsp, } } else { - uint32_t access_granted = 0; - fsp->fh->fd = -1; /* What we used to call a stat open. */ if (!file_existed) { /* File must exist for a stat open. */ @@ -589,79 +660,26 @@ static NTSTATUS open_file(files_struct *fsp, status = smbd_check_open_rights(conn, smb_fname, - access_mask, - &access_granted); - if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) { - /* - * On NT_STATUS_ACCESS_DENIED, access_granted - * contains the denied bits. - */ + access_mask); - if ((access_mask & FILE_WRITE_ATTRIBUTES) && - (access_granted & FILE_WRITE_ATTRIBUTES) && - (lp_map_readonly(SNUM(conn)) || - lp_map_archive(SNUM(conn)) || - lp_map_hidden(SNUM(conn)) || - lp_map_system(SNUM(conn)))) { -- Samba Shared Repository