The branch, master has been updated via df8e9c1 s3-selftest: Add a seperate test for ACL tests using vfstest via 05885a8 s3-torture: Add ACL commands to vfstest via 345b980 s3-torture: Use talloc more in vfstest via 43255a1 s3-torture: Initialise fsp fully in vfstest open via 1157db2 s3-smbd: Do not check no_acl_syscall_error(errno) after sys_acl_init() via 802d67c selftest: Extend xattr-tdb-1 vfstest to call stat via 820d179 s3-vfs: Continue to make vfs_xattr_tdb non-recursive via 843e19e s3-vfs: Add new VFS module to fake setting an ACL via 2129495 librpc/idl: Fix acl array definition in smb_acl_t from 97e7c3b s3-selftest: convert xattr-tdb-1 vfstest driver into a subunit test
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit df8e9c128716c89f5a1d58f032e3d641e033c8b0 Author: Andrew Bartlett <abart...@samba.org> Date: Thu Aug 16 13:46:02 2012 +1000 s3-selftest: Add a seperate test for ACL tests using vfstest This does not check for consistency or correctness yet, that will be done with python unit tests. The purpose of this test is to ensure that the vfstest wrapper doesn't crash. Andrew Bartlett Autobuild-User(master): Andrew Bartlett <abart...@samba.org> Autobuild-Date(master): Thu Aug 16 09:32:25 CEST 2012 on sn-devel-104 commit 05885a84f9ea67a986bdcb10a2bd07c00a2df0d4 Author: Andrew Bartlett <abart...@samba.org> Date: Thu Aug 16 13:44:48 2012 +1000 s3-torture: Add ACL commands to vfstest This will allow easier investigation of our ACL layer. Andrew Bartlett commit 345b980c3e55645009150ef9a7ab35245e8e55db Author: Andrew Bartlett <abart...@samba.org> Date: Thu Aug 16 15:16:01 2012 +1000 s3-torture: Use talloc more in vfstest This matches the rest of Samba, which allocates many of these structures with talloc. Andrew Bartlett commit 43255a1d18b714ab108b21f5a1065a82e44e3490 Author: Andrew Bartlett <abart...@samba.org> Date: Thu Aug 16 14:37:42 2012 +1000 s3-torture: Initialise fsp fully in vfstest open commit 1157db293f5db7909f84f021581ddb916cfd8c7e Author: Andrew Bartlett <abart...@samba.org> Date: Thu Aug 16 13:44:01 2012 +1000 s3-smbd: Do not check no_acl_syscall_error(errno) after sys_acl_init() This is no longer a VFS call, so will no longer fail in this way. Andrew Bartlett commit 802d67cabe63f5c1e9f5445fc9e5ef26dca43efe Author: Andrew Bartlett <abart...@samba.org> Date: Thu Aug 16 10:03:35 2012 +1000 selftest: Extend xattr-tdb-1 vfstest to call stat commit 820d1795d739706c45fdf32adbaaf5d817eef868 Author: Andrew Bartlett <abart...@samba.org> Date: Thu Aug 16 10:02:44 2012 +1000 s3-vfs: Continue to make vfs_xattr_tdb non-recursive We now always use _NEXT_ VFS calls, even to build the file id. Andrew Bartlett commit 843e19eff40d300e1b671fb0e78300e6a4cc3683 Author: Andrew Bartlett <abart...@samba.org> Date: Wed Aug 15 20:34:41 2012 +1000 s3-vfs: Add new VFS module to fake setting an ACL The purpose of this module is to remove the relience on the system having ACL support to test NT ACLs. Andrew Bartlett commit 2129495319adda28dbe21e1ac9846fcae9373989 Author: Andrew Bartlett <abart...@samba.org> Date: Thu Aug 16 14:13:00 2012 +1000 librpc/idl: Fix acl array definition in smb_acl_t ----------------------------------------------------------------------- Summary of changes: librpc/idl/smb_acl.idl | 2 +- selftest/knownfail | 1 + source3/modules/vfs_fake_acls.c | 374 +++++++++++++++++++ source3/modules/vfs_xattr_tdb.c | 74 +++-- .../tests/{xattr-tdb-1 => vfstest-acl}/run.sh | 0 source3/script/tests/vfstest-acl/vfstest.cmd | 6 + source3/script/tests/xattr-tdb-1/vfstest.cmd | 1 + source3/selftest/tests.py | 2 +- source3/smbd/posix_acls.c | 13 +- source3/torture/cmd_vfs.c | 385 +++++++++++++++++++- source3/torture/vfstest.c | 35 +- source3/wscript | 4 + 12 files changed, 833 insertions(+), 64 deletions(-) create mode 100644 source3/modules/vfs_fake_acls.c copy source3/script/tests/{xattr-tdb-1 => vfstest-acl}/run.sh (100%) create mode 100644 source3/script/tests/vfstest-acl/vfstest.cmd Changeset truncated at 500 lines: diff --git a/librpc/idl/smb_acl.idl b/librpc/idl/smb_acl.idl index 856312f..7f67299 100644 --- a/librpc/idl/smb_acl.idl +++ b/librpc/idl/smb_acl.idl @@ -52,7 +52,7 @@ interface smb_acl int size; int count; int next; - smb_acl_entry *acl; + [size_is(count)] smb_acl_entry acl[*]; } smb_acl_t; const int SMB_ACL_FIRST_ENTRY = 0; diff --git a/selftest/knownfail b/selftest/knownfail index dbd2616..da3d93c 100644 --- a/selftest/knownfail +++ b/selftest/knownfail @@ -46,6 +46,7 @@ # these show that we still have some differences between our system # with our internal iconv because it passes except when we bypass our # internal iconv modules +^samba.vfstest.acl.vfstest\(s3dc:local\) #until we get the fake_acls module into selftest ^samba4.local.convert_string_handle.system.iconv.gd_ascii ^samba4.local.convert_string_handle.system.iconv.gd_iso8859_cp850 ^samba4..*base.delete.*.deltest17 diff --git a/source3/modules/vfs_fake_acls.c b/source3/modules/vfs_fake_acls.c new file mode 100644 index 0000000..175d6d2 --- /dev/null +++ b/source3/modules/vfs_fake_acls.c @@ -0,0 +1,374 @@ +/* + * Fake ACLs VFS module. Implements passthrough operation of all VFS + * calls to disk functions, except for file ownership and ACLs, which + * are stored in xattrs. + * + * Copyright (C) Tim Potter, 1999-2000 + * Copyright (C) Alexander Bokovoy, 2002 + * Copyright (C) Andrew Bartlett, 2002,2012 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "includes.h" +#include "smbd/smbd.h" +#include "system/filesys.h" +#include "auth.h" +#include "librpc/gen_ndr/ndr_smb_acl.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_VFS + +#define FAKE_UID "FAKE.uid" +#define FAKE_GID "FAKE.gid" +#define FAKE_ACL_ACCESS_XATTR "FAKE.access_acl" +#define FAKE_ACL_DEFAULT_XATTR "FAKE.default_acl" + +static int fake_acls_uid(vfs_handle_struct *handle, + const char *path, + uid_t *uid) +{ + ssize_t size; + uint8_t uid_buf[4]; + size = SMB_VFS_NEXT_GETXATTR(handle, path, FAKE_UID, uid_buf, sizeof(uid_buf)); + if (size == -1 && errno == ENOATTR) { + return 0; + } + if (size != 4) { + return -1; + } + *uid = IVAL(uid_buf, 0); + return 0; +} + +static int fake_acls_gid(vfs_handle_struct *handle, + const char *path, + uid_t *gid) +{ + ssize_t size; + uint8_t gid_buf[4]; + + size = SMB_VFS_NEXT_GETXATTR(handle, path, FAKE_GID, gid_buf, sizeof(gid_buf)); + if (size == -1 && errno == ENOATTR) { + return 0; + } + if (size != 4) { + return -1; + } + *gid = IVAL(gid_buf, 0); + return 0; +} + +static int fake_acls_fuid(vfs_handle_struct *handle, + files_struct *fsp, + uid_t *uid) +{ + ssize_t size; + uint8_t uid_buf[4]; + + size = SMB_VFS_NEXT_FGETXATTR(handle, fsp, FAKE_UID, uid_buf, sizeof(uid_buf)); + if (size == -1 && errno == ENOATTR) { + return 0; + } + if (size != 4) { + return -1; + } + *uid = IVAL(uid_buf, 0); + return 0; +} + +static int fake_acls_fgid(vfs_handle_struct *handle, + files_struct *fsp, + uid_t *gid) +{ + ssize_t size; + uint8_t gid_buf[4]; + + size = SMB_VFS_NEXT_FGETXATTR(handle, fsp, FAKE_GID, gid_buf, sizeof(gid_buf)); + if (size == -1 && errno == ENOATTR) { + return 0; + } + if (size != 4) { + return -1; + } + *gid = IVAL(gid_buf, 0); + return 0; +} + +static int fake_acls_stat(vfs_handle_struct *handle, + struct smb_filename *smb_fname) +{ + int ret = -1; + + ret = SMB_VFS_NEXT_STAT(handle, smb_fname); + if (ret == 0) { + TALLOC_CTX *frame = talloc_stackframe(); + char *path; + NTSTATUS status; + status = get_full_smb_filename(frame, smb_fname, &path); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + TALLOC_FREE(frame); + return -1; + } + + ret = fake_acls_uid(handle, path, &smb_fname->st.st_ex_uid); + if (ret != 0) { + TALLOC_FREE(frame); + return ret; + } + ret = fake_acls_gid(handle, path, &smb_fname->st.st_ex_gid); + if (ret != 0) { + TALLOC_FREE(frame); + return ret; + } + TALLOC_FREE(frame); + } + + return ret; +} + +static int fake_acls_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf) +{ + int ret = -1; + + ret = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf); + if (ret == 0) { + ret = fake_acls_fuid(handle, fsp, &sbuf->st_ex_uid); + if (ret != 0) { + return ret; + } + ret = fake_acls_fgid(handle, fsp, &sbuf->st_ex_gid); + if (ret != 0) { + return ret; + } + } + return ret; +} + +static SMB_ACL_T fake_acls_blob2acl(DATA_BLOB *blob) +{ + enum ndr_err_code ndr_err; + /* For now, ACLs are allocated on NULL */ + struct smb_acl_t *acl = talloc(NULL, struct smb_acl_t); + if (!acl) { + errno = ENOMEM; + return NULL; + } + + ndr_err = ndr_pull_struct_blob(blob, acl, acl, + (ndr_pull_flags_fn_t)ndr_pull_smb_acl_t); + + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + DEBUG(0, ("ndr_pull_acl_t failed: %s\n", + ndr_errstr(ndr_err))); + TALLOC_FREE(acl); + return NULL; + } + return acl; +} + +static DATA_BLOB fake_acls_acl2blob(TALLOC_CTX *mem_ctx, SMB_ACL_T acl) +{ + enum ndr_err_code ndr_err; + DATA_BLOB blob; + ndr_err = ndr_push_struct_blob(&blob, mem_ctx, acl, + (ndr_push_flags_fn_t)ndr_push_smb_acl_t); + + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + DEBUG(0, ("ndr_push_acl_t failed: %s\n", + ndr_errstr(ndr_err))); + return data_blob_null; + } + return blob; +} + +static SMB_ACL_T fake_acls_sys_acl_get_file(struct vfs_handle_struct *handle, const char *path, SMB_ACL_TYPE_T type) +{ + DATA_BLOB blob = data_blob_null; + ssize_t length; + const char *name = NULL; + struct smb_acl_t *acl = NULL; + TALLOC_CTX *frame = talloc_stackframe(); + switch (type) { + case SMB_ACL_TYPE_ACCESS: + name = FAKE_ACL_ACCESS_XATTR; + break; + case SMB_ACL_TYPE_DEFAULT: + name = FAKE_ACL_DEFAULT_XATTR; + break; + } + + do { + blob.length += 1000; + blob.data = talloc_realloc(frame, blob.data, uint8_t, blob.length); + if (!blob.data) { + errno = ENOMEM; + TALLOC_FREE(frame); + return NULL; + } + length = SMB_VFS_NEXT_GETXATTR(handle, path, name, blob.data, blob.length); + blob.length = length; + } while (length == -1 && errno == ERANGE); + if (length == -1 && errno == ENOATTR) { + TALLOC_FREE(frame); + return NULL; + } + if (length != -1) { + acl = fake_acls_blob2acl(&blob); + } + TALLOC_FREE(frame); + return acl; +} + +static SMB_ACL_T fake_acls_sys_acl_get_fd(struct vfs_handle_struct *handle, files_struct *fsp) +{ + DATA_BLOB blob = data_blob_null; + ssize_t length; + const char *name = FAKE_ACL_ACCESS_XATTR; + struct smb_acl_t *acl; + TALLOC_CTX *frame = talloc_stackframe(); + + do { + blob.length += 1000; + blob.data = talloc_realloc(frame, blob.data, uint8_t, blob.length); + if (!blob.data) { + errno = ENOMEM; + TALLOC_FREE(frame); + return NULL; + } + length = SMB_VFS_NEXT_FGETXATTR(handle, fsp, name, blob.data, blob.length); + blob.length = length; + } while (length == -1 && errno == ERANGE); + if (length == -1 && errno == ENOATTR) { + TALLOC_FREE(frame); + return NULL; + } + if (length != -1) { + acl = fake_acls_blob2acl(&blob); + } + TALLOC_FREE(frame); + return acl; +} + +static int fake_acls_sys_acl_set_file(vfs_handle_struct *handle, const char *path, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) +{ + int ret; + const char *name = NULL; + TALLOC_CTX *frame = talloc_stackframe(); + DATA_BLOB blob = fake_acls_acl2blob(frame, theacl); + if (!blob.data) { + DEBUG(0, ("Failed to convert ACL to linear blob for xattr storage\n")); + TALLOC_FREE(frame); + errno = EINVAL; + return -1; + } + switch (acltype) { + case SMB_ACL_TYPE_ACCESS: + name = FAKE_ACL_ACCESS_XATTR; + break; + case SMB_ACL_TYPE_DEFAULT: + name = FAKE_ACL_DEFAULT_XATTR; + break; + } + ret = SMB_VFS_NEXT_SETXATTR(handle, path, name, blob.data, blob.length, 0); + TALLOC_FREE(frame); + return ret; +} + +static int fake_acls_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, SMB_ACL_T theacl) +{ + int ret; + const char *name = FAKE_ACL_ACCESS_XATTR; + TALLOC_CTX *frame = talloc_stackframe(); + DATA_BLOB blob = fake_acls_acl2blob(frame, theacl); + if (!blob.data) { + DEBUG(0, ("Failed to convert ACL to linear blob for xattr storage\n")); + TALLOC_FREE(frame); + errno = EINVAL; + return -1; + } + ret = SMB_VFS_NEXT_FSETXATTR(handle, fsp, name, blob.data, blob.length, 0); + TALLOC_FREE(frame); + return ret; +} + +static int fake_acls_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path) +{ + const char *name = FAKE_ACL_DEFAULT_XATTR; + return SMB_VFS_NEXT_REMOVEXATTR(handle, path, name); +} + +static int fake_acls_chown(vfs_handle_struct *handle, const char *path, uid_t uid, gid_t gid) +{ + int ret; + uint8_t id_buf[4]; + if (uid != -1) { + SIVAL(id_buf, 0, uid); + ret = SMB_VFS_NEXT_SETXATTR(handle, path, FAKE_UID, id_buf, sizeof(id_buf), 0); + if (ret != 0) { + return ret; + } + } + if (gid != -1) { + SIVAL(id_buf, 0, gid); + ret = SMB_VFS_NEXT_SETXATTR(handle, path, FAKE_GID, id_buf, sizeof(id_buf), 0); + if (ret != 0) { + return ret; + } + } + return 0; +} + +static int fake_acls_fchown(vfs_handle_struct *handle, files_struct *fsp, uid_t uid, gid_t gid) +{ + int ret; + uint8_t id_buf[4]; + if (uid != -1) { + SIVAL(id_buf, 0, uid); + ret = SMB_VFS_NEXT_FSETXATTR(handle, fsp, FAKE_UID, id_buf, sizeof(id_buf), 0); + if (ret != 0) { + return ret; + } + } + if (gid != -1) { + SIVAL(id_buf, 0, gid); + ret = SMB_VFS_NEXT_FSETXATTR(handle, fsp, FAKE_GID, id_buf, sizeof(id_buf), 0); + if (ret != 0) { + return ret; + } + } + return 0; +} + + +static struct vfs_fn_pointers vfs_fake_acls_fns = { + .stat_fn = fake_acls_stat, + .fstat_fn = fake_acls_fstat, + .sys_acl_get_file_fn = fake_acls_sys_acl_get_file, + .sys_acl_get_fd_fn = fake_acls_sys_acl_get_fd, + .sys_acl_set_file_fn = fake_acls_sys_acl_set_file, + .sys_acl_set_fd_fn = fake_acls_sys_acl_set_fd, + .sys_acl_delete_def_file_fn = fake_acls_sys_acl_delete_def_file, + .chown_fn = fake_acls_chown, + .fchown_fn = fake_acls_fchown, + +}; + +NTSTATUS vfs_fake_acls_init(void); +NTSTATUS vfs_fake_acls_init(void) +{ + return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "fake_acls", + &vfs_fake_acls_fns); +} diff --git a/source3/modules/vfs_xattr_tdb.c b/source3/modules/vfs_xattr_tdb.c index 719ac0c..67f6bcb 100644 --- a/source3/modules/vfs_xattr_tdb.c +++ b/source3/modules/vfs_xattr_tdb.c @@ -27,27 +27,52 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_VFS +static int xattr_tdb_get_file_id(struct vfs_handle_struct *handle, + const char *path, struct file_id *id) +{ + int ret; + TALLOC_CTX *frame = talloc_stackframe(); + struct smb_filename *smb_fname = NULL; + NTSTATUS status = create_synthetic_smb_fname_split(frame, path, NULL, + &smb_fname); + if (!NT_STATUS_IS_OK(status)) { + errno = map_errno_from_nt_status(status); + TALLOC_FREE(frame); + return -1; + } + + ret = SMB_VFS_NEXT_STAT(handle, smb_fname); + + if (ret == -1) { + TALLOC_FREE(frame); + return -1; + } + + *id = SMB_VFS_NEXT_FILE_ID_CREATE(handle, &smb_fname->st); + TALLOC_FREE(frame); + return 0; +} + static ssize_t xattr_tdb_getxattr(struct vfs_handle_struct *handle, const char *path, const char *name, void *value, size_t size) { - SMB_STRUCT_STAT sbuf; struct file_id id; struct db_context *db; ssize_t xattr_size; + int ret; DATA_BLOB blob; TALLOC_CTX *frame = talloc_stackframe(); SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, TALLOC_FREE(frame); return -1); - if (vfs_stat_smb_fname(handle->conn, path, &sbuf) == -1) { + ret = xattr_tdb_get_file_id(handle, path, &id); + if (ret == -1) { TALLOC_FREE(frame); return -1; } - id = SMB_VFS_FILE_ID_CREATE(handle->conn, &sbuf); - xattr_size = xattr_tdb_getattr(db, frame, &id, name, &blob); if (xattr_size < 0) { errno = ENOATTR; @@ -82,7 +107,7 @@ static ssize_t xattr_tdb_fgetxattr(struct vfs_handle_struct *handle, return -1; } - id = SMB_VFS_FILE_ID_CREATE(handle->conn, &sbuf); + id = SMB_VFS_NEXT_FILE_ID_CREATE(handle, &sbuf); xattr_size = xattr_tdb_getattr(db, frame, &id, name, &blob); if (xattr_size < 0) { @@ -104,18 +129,17 @@ static int xattr_tdb_setxattr(struct vfs_handle_struct *handle, const char *path, const char *name, const void *value, size_t size, int flags) { - SMB_STRUCT_STAT sbuf; struct file_id id; struct db_context *db; + int ret; SMB_VFS_HANDLE_GET_DATA(handle, db, struct db_context, return -1); - if (vfs_stat_smb_fname(handle->conn, path, &sbuf) == -1) { + ret = xattr_tdb_get_file_id(handle, path, &id); + if (ret == -1) { return -1; } - id = SMB_VFS_FILE_ID_CREATE(handle->conn, &sbuf); - return xattr_tdb_setattr(db, &id, name, value, size, flags); } @@ -134,7 +158,7 @@ static int xattr_tdb_fsetxattr(struct vfs_handle_struct *handle, return -1; } -- Samba Shared Repository