The branch, master has been updated via 85b8cccab072bab263061654b677bc84826646c9 (commit) via 239f815e30a4e5f64112a8da6401614eb3218eb5 (commit) from c09e04ac83365333605b7b1db3d07ccfd451a667 (commit)
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 85b8cccab072bab263061654b677bc84826646c9 Author: Steven Danneman <[EMAIL PROTECTED]> Date: Tue Dec 2 20:15:34 2008 -0800 Add support for OneFS ACLs Add to the OneFS VFS module, support for NTFS ACLs through the calls: SMB_VFS_FGET_NT_ACL() SMB_VFS_GET_NT_ACL() SMB_VFS_FSET_NT_ACL() Also create several new onefs specific smb.conf parameters in onefs.h commit 239f815e30a4e5f64112a8da6401614eb3218eb5 Author: Tim Prouty <[EMAIL PROTECTED]> Date: Thu Oct 23 20:49:55 2008 -0700 Add OneFS VFS module skeleton. Also set configure to autodetect OneFS OS and build this VFS module. ----------------------------------------------------------------------- Summary of changes: source3/Makefile.in | 5 + source3/configure.in | 19 + source3/modules/onefs.h | 52 +++ source3/modules/onefs_acl.c | 807 +++++++++++++++++++++++++++++++++++++++++++ source3/modules/vfs_onefs.c | 48 +++ 5 files changed, 931 insertions(+), 0 deletions(-) create mode 100644 source3/modules/onefs.h create mode 100644 source3/modules/onefs_acl.c create mode 100644 source3/modules/vfs_onefs.c Changeset truncated at 500 lines: diff --git a/source3/Makefile.in b/source3/Makefile.in index 37c48d4..83e94a4 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -650,6 +650,7 @@ VFS_SYNCOPS_OBJ = modules/vfs_syncops.o VFS_ACL_XATTR_OBJ = modules/vfs_acl_xattr.o VFS_ACL_TDB_OBJ = modules/vfs_acl_tdb.o VFS_SMB_TRAFFIC_ANALYZER_OBJ = modules/vfs_smb_traffic_analyzer.o +VFS_ONEFS_OBJ = modules/vfs_onefs.o modules/onefs_acl.o PLAINTEXT_AUTH_OBJ = auth/pampass.o auth/pass_check.o @@ -2479,6 +2480,10 @@ bin/[EMAIL PROTECTED]@: $(BINARY_PREREQS) $(VFS_ACL_TDB_OBJ) @echo "Building plugin $@" @$(SHLD_MODULE) $(VFS_ACL_TDB_OBJ) +bin/[EMAIL PROTECTED]@: $(BINARY_PREREQS) $(VFS_ONEFS_OBJ) + @echo "Building plugin $@" + @$(SHLD_MODULE) $(VFS_ONEFS_OBJ) @ONEFS_LIBS@ + bin/[EMAIL PROTECTED]@: $(BINARY_PREREQS) libgpo/gpext/registry.o @echo "Building plugin $@" @$(SHLD_MODULE) libgpo/gpext/registry.o diff --git a/source3/configure.in b/source3/configure.in index 79bd63d..40e78e8 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -1052,6 +1052,24 @@ if test x"$samba_cv_HAVE_GPFS" = x"yes"; then fi LIBS="$save_LIBS" +############################################# +# check if building on Isilon OneFS +printf "%s" "checking for Isilon OneFS... " +save_LIBS="$LIBS" +LIBS="$LIBS -lisi_version" +AC_TRY_LINK([#include <isi_version/isi_version.h>], + [get_isilon_copyright()], + samba_cv_HAVE_ONEFS=yes, + samba_cv_HAVE_ONEFS=no) +echo $samba_cv_HAVE_ONEFS +if test x"$samba_cv_HAVE_ONEFS" = x"yes"; then + AC_DEFINE(HAVE_ONEFS,1,[Whether building on Isilon OneFS]) + default_shared_modules="$default_shared_modules vfs_onefs" + ONEFS_LIBS="-lisi_acl" +fi +AC_SUBST(ONEFS_LIBS) +LIBS="$save_LIBS" + # Note that all the libunwind symbols in the API are defined to internal # platform-specific version, so we must include libunwind.h before checking # any of them. @@ -6127,6 +6145,7 @@ SMB_MODULE(vfs_notify_fam, \$(VFS_NOTIFY_FAM_OBJ), "bin/notify_fam.$SHLIBEXT", V SMB_MODULE(vfs_acl_xattr, \$(VFS_ACL_XATTR_OBJ), "bin/acl_xattr.$SHLIBEXT", VFS) SMB_MODULE(vfs_acl_tdb, \$(VFS_ACL_TDB_OBJ), "bin/acl_tdb.$SHLIBEXT", VFS) SMB_MODULE(vfs_smb_traffic_analyzer, \$(VFS_SMB_TRAFFIC_ANALYZER_OBJ), "bin/smb_traffic_analyzer.$SHLIBEXT", VFS) +SMB_MODULE(vfs_onefs, \$(VFS_ONEFS), "bin/onefs.$SHLIBEXT", VFS) SMB_SUBSYSTEM(VFS,smbd/vfs.o) diff --git a/source3/modules/onefs.h b/source3/modules/onefs.h new file mode 100644 index 0000000..965f395 --- /dev/null +++ b/source3/modules/onefs.h @@ -0,0 +1,52 @@ +/* + * Unix SMB/CIFS implementation. + * Support for OneFS + * + * Copyright (C) Steven Danneman, 2008 + * + * 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/>. + */ + +#ifndef _ONEFS_H +#define _ONEFS_H + +/* OneFS Module smb.conf parameters and defaults */ + +/** +* Specifies when ACLs presented to Windows should be canonicalized +* into the ordering which Explorer expects. +*/ +enum onefs_acl_wire_format +{ + ACL_FORMAT_RAW, /**< Never canonicalize */ + ACL_FORMAT_WINDOWS_SD, /**< Only canonicalize synthetic ACLs */ + ACL_FORMAT_ALWAYS /**< Always canonicalize */ +}; + +const struct enum_list enum_onefs_acl_wire_format[] = { + {ACL_FORMAT_RAW, "No Format"}, + {ACL_FORMAT_WINDOWS_SD, "Format Windows SD"}, + {ACL_FORMAT_ALWAYS, "Always Format SD"}, + {-1, NULL} +}; + +#define PARM_ONEFS_TYPE "onefs" +#define PARM_ACL_WIRE_FORMAT "acl wire format" +#define PARM_ACL_WIRE_FORMAT_DEFAULT ACL_FORMAT_WINDOWS_SD +#define PARM_SIMPLE_FILE_SHARING_COMPATIBILITY_MODE "simple file sharing compatibility mode" +#define PARM_SIMPLE_FILE_SHARING_COMPATIBILITY_MODE_DEFAULT false +#define PARM_CREATOR_OWNER_GETS_FULL_CONTROL "creator owner gets full control" +#define PARM_CREATOR_OWNER_GETS_FULL_CONTROL_DEFAULT true + +#endif /* _ONEFS_H */ diff --git a/source3/modules/onefs_acl.c b/source3/modules/onefs_acl.c new file mode 100644 index 0000000..3a692c9 --- /dev/null +++ b/source3/modules/onefs_acl.c @@ -0,0 +1,807 @@ +/* + * Unix SMB/CIFS implementation. + * + * Support for OneFS native NTFS ACLs + * + * Copyright (C) Steven Danneman, 2008 + * + * 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 <sys/isi_acl.h> +#include <isi_acl/isi_acl_util.h> +#include <sys/isi_oplock.h> +#include <ifs/ifs_syscalls.h> + +#include "onefs.h" + +/** + * Turn SID into UID/GID and setup a struct ifs_identity + */ +static bool +onefs_sid_to_identity(DOM_SID *sid, struct ifs_identity *id, bool is_group) +{ + enum ifs_identity_type type = IFS_ID_TYPE_LAST+1; + uid_t uid = 0; + gid_t gid = 0; + + if (!sid || sid_equal(sid, &global_sid_NULL)) + type = IFS_ID_TYPE_NULL; + else if (sid_equal(sid, &global_sid_World)) + type = IFS_ID_TYPE_EVERYONE; + else if (sid_equal(sid, &global_sid_Creator_Owner)) + type = IFS_ID_TYPE_CREATOR_OWNER; + else if (sid_equal(sid, &global_sid_Creator_Group)) + type = IFS_ID_TYPE_CREATOR_GROUP; + else if (is_group) { + if (!sid_to_gid(sid, &gid)) + return false; + type = IFS_ID_TYPE_GID; + } else { + if (sid_to_uid(sid, &uid)) + type = IFS_ID_TYPE_UID; + else if (sid_to_gid(sid, &gid)) + type = IFS_ID_TYPE_GID; + else + return false; + } + + if (aclu_initialize_identity(id, type, uid, gid, is_group)) { + DEBUG(3, ("Call to aclu_initialize_identity failed! id=%x, " + "type=%d, uid=%u, gid=%u, is_group=%d\n", + (unsigned int)id, type, uid, gid, is_group)); + return false; + } + + return true; +} + +/** + * Turn struct ifs_identity into SID + */ +static bool +onefs_identity_to_sid(struct ifs_identity *id, DOM_SID *sid) +{ + if (!id || !sid) + return false; + + if (id->type >= IFS_ID_TYPE_LAST) + return false; + + switch (id->type) { + case IFS_ID_TYPE_UID: + uid_to_sid(sid, id->id.uid); + break; + case IFS_ID_TYPE_GID: + gid_to_sid(sid, id->id.gid); + break; + case IFS_ID_TYPE_EVERYONE: + sid_copy(sid, &global_sid_World); + break; + case IFS_ID_TYPE_NULL: + sid_copy(sid, &global_sid_NULL); + break; + case IFS_ID_TYPE_CREATOR_OWNER: + sid_copy(sid, &global_sid_Creator_Owner); + break; + case IFS_ID_TYPE_CREATOR_GROUP: + sid_copy(sid, &global_sid_Creator_Group); + break; + default: + DEBUG(0, ("Unknown identity type: %d\n", id->type)); + return false; + } + + return true; +} + +/** + * Convert a SEC_ACL to a struct ifs_security_acl + */ +static bool +onefs_samba_acl_to_acl(SEC_ACL *samba_acl, struct ifs_security_acl **acl) +{ + int num_aces = 0; + struct ifs_ace *aces = NULL; + struct ifs_identity temp; + SEC_ACE *samba_aces; + int i, j; + + if ((!acl) || (!samba_acl)) + return false; + + samba_aces = samba_acl->aces; + + if (samba_acl->num_aces > 0 && samba_aces) { + /* Setup ACES */ + num_aces = samba_acl->num_aces; + aces = SMB_MALLOC_ARRAY(struct ifs_ace, num_aces); + + for (i = 0, j = 0; j < num_aces; i++, j++) { + if (!onefs_sid_to_identity(&samba_aces[j].trustee, + &temp, false)) + goto err_free; + + /* + * XXX Act like we did pre-Thai: Silently fail setting + * ACEs for BUILTIN accounts. + */ + if (temp.id.uid == -1) { + DEBUG(3, ("Silently failing to set ACE " + "because our id was == -1.\n")); + i--; + continue; + } + + if (aclu_initialize_ace(&aces[i], samba_aces[i].type, + samba_aces[i].access_mask, samba_aces[i].flags, + 0, &temp)) + goto err_free; + + if ((aces[i].trustee.type == IFS_ID_TYPE_CREATOR_OWNER || + aces[i].trustee.type == IFS_ID_TYPE_CREATOR_GROUP) && + nt4_compatible_acls()) + aces[i].flags |= IFS_ACE_FLAG_INHERIT_ONLY; + } + num_aces = i; + } + + if (aclu_initialize_acl(acl, aces, num_aces)) + goto err_free; + + /* Currently aclu_initialize_acl should copy the aces over, allowing us + * to immediately free */ + free(aces); + return true; + +err_free: + free(aces); + return false; +} + +/** + * Convert a struct ifs_security_acl to a SEC_ACL + */ +static bool +onefs_acl_to_samba_acl(struct ifs_security_acl *acl, SEC_ACL **samba_acl) +{ + SEC_ACE *samba_aces = NULL; + SEC_ACL *tmp_samba_acl = NULL; + int i, num_aces = 0; + + if (!samba_acl) + return false; + + /* NULL ACL */ + if (!acl) { + *samba_acl = NULL; + return true; + } + + /* Determine number of aces in ACL */ + if (!acl->aces) + num_aces = 0; + else + num_aces = acl->num_aces; + + /* Allocate the ace list. */ + if (num_aces > 0) { + if ((samba_aces = SMB_MALLOC_ARRAY(SEC_ACE, num_aces)) == NULL) + { + DEBUG(0, ("Unable to malloc space for %d aces.\n", + num_aces)); + return false; + } + memset(samba_aces, '\0', (num_aces) * sizeof(SEC_ACE)); + } + + for (i = 0; i < num_aces; i++) { + DOM_SID sid; + + if (!onefs_identity_to_sid(&acl->aces[i].trustee, &sid)) + goto err_free; + + init_sec_ace(&samba_aces[i], &sid, acl->aces[i].type, + acl->aces[i].access_mask, acl->aces[i].flags); + } + + if ((tmp_samba_acl = make_sec_acl(talloc_tos(), acl->revision, num_aces, + samba_aces)) == NULL) { + DEBUG(0, ("Unable to malloc space for acl.\n")); + goto err_free; + } + + *samba_acl = tmp_samba_acl; + SAFE_FREE(samba_aces); + return true; +err_free: + SAFE_FREE(samba_aces); + return false; +} + +/** + * @brief Reorder ACLs into the "correct" order for Windows Explorer. + * + * Windows Explorer expects ACLs to be in a standard order (inherited first, + * then deny, then permit.) When ACLs are composed from POSIX file permissions + * bits, they may not match these expectations, generating an annoying warning + * dialog for the user. This function will, if configured appropriately, + * reorder the ACLs for these "synthetic" (POSIX-derived) descriptors to prevent + * this. The list is changed within the security descriptor passed in. + * + * @param fsp files_struct with service configs; must not be NULL + * @param sd security descriptor being normalized; + * sd->dacl->aces is rewritten in-place, so must not be NULL + * @return true on success, errno will be set on error + * + * @bug Although Windows Explorer likes the reordering, they seem to cause + * problems with Excel and Word sending back the reordered ACLs to us and + * changing policy; see Isilon bug 30165. + */ +static bool +onefs_canon_acl(files_struct *fsp, struct ifs_security_descriptor *sd) +{ + int error = 0; + int cur; + struct ifs_ace *new_aces = NULL; + int new_aces_count = 0; + SMB_STRUCT_STAT sbuf; + + if (sd == NULL || sd->dacl == NULL || sd->dacl->num_aces == 0) + return true; + + /* + * Find out if this is a windows bit, and if the smb policy wants us to + * lie about the sd. + */ + SMB_ASSERT(fsp != NULL); + switch (lp_parm_enum(SNUM(fsp->conn), PARM_ONEFS_TYPE, + PARM_ACL_WIRE_FORMAT, enum_onefs_acl_wire_format, + PARM_ACL_WIRE_FORMAT_DEFAULT)) { + case ACL_FORMAT_RAW: + return true; + + case ACL_FORMAT_WINDOWS_SD: + error = SMB_VFS_FSTAT(fsp, &sbuf); + if (error) + return false; + + if ((sbuf.st_flags & SF_HASNTFSACL) != 0) { + DEBUG(10, ("Did not canonicalize ACLs because a " + "Windows ACL set was found for file %s\n", + fsp->fsp_name)); + return true; + } + break; + + case ACL_FORMAT_ALWAYS: + break; + + default: + SMB_ASSERT(false); + return false; + } + + new_aces = SMB_MALLOC_ARRAY(struct ifs_ace, sd->dacl->num_aces); + if (new_aces == NULL) + return false; + + /* + * By walking down the list 3 separate times, we can avoid the need + * to create multiple temp buffers and extra copies. + */ + for (cur = 0; cur < sd->dacl->num_aces; cur++) { + if (sd->dacl->aces[cur].flags & IFS_ACE_FLAG_INHERITED_ACE) + new_aces[new_aces_count++] = sd->dacl->aces[cur]; + } + + for (cur = 0; cur < sd->dacl->num_aces; cur++) { + if (!(sd->dacl->aces[cur].flags & IFS_ACE_FLAG_INHERITED_ACE) && + (sd->dacl->aces[cur].type == IFS_ACE_TYPE_ACCESS_DENIED)) + new_aces[new_aces_count++] = sd->dacl->aces[cur]; + } + + for (cur = 0; cur < sd->dacl->num_aces; cur++) { + if (!(sd->dacl->aces[cur].flags & IFS_ACE_FLAG_INHERITED_ACE) && + !(sd->dacl->aces[cur].type == IFS_ACE_TYPE_ACCESS_DENIED)) + new_aces[new_aces_count++] = sd->dacl->aces[cur]; + } + + SMB_ASSERT(new_aces_count == sd->dacl->num_aces); + DEBUG(10, ("Performed canonicalization of ACLs for file %s\n", + fsp->fsp_name)); + + /* + * At this point you would think we could just do this: + * SAFE_FREE(sd->dacl->aces); + * sd->dacl->aces = new_aces; + * However, in some cases the existing aces pointer does not point + * to the beginning of an allocated block. So we have to do a more + * expensive memcpy() + */ + memcpy(sd->dacl->aces, new_aces, + sizeof(struct ifs_ace) * new_aces_count); + + SAFE_FREE(new_aces); + return true; +} + + +/** + * This enum is a helper for onefs_fget_nt_acl() to communicate with + * onefs_init_ace(). + */ +enum mode_ident { USR, GRP, OTH }; + +/** + * Initializes an ACE for addition to a synthetic ACL. + */ +static struct ifs_ace onefs_init_ace(struct connection_struct *conn, + mode_t mode, + bool isdir, + enum mode_ident ident) +{ + struct ifs_ace result; + enum ifs_ace_rights r,w,x; + + r = isdir ? UNIX_DIRECTORY_ACCESS_R : UNIX_ACCESS_R; + w = isdir ? UNIX_DIRECTORY_ACCESS_W : UNIX_ACCESS_W; + x = isdir ? UNIX_DIRECTORY_ACCESS_X : UNIX_ACCESS_X; + + result.type = IFS_ACE_TYPE_ACCESS_ALLOWED; + result.ifs_flags = 0; + result.flags = isdir ? IFS_ACE_FLAG_CONTAINER_INHERIT : + IFS_ACE_FLAG_OBJECT_INHERIT; + result.flags |= IFS_ACE_FLAG_INHERIT_ONLY; + + switch (ident) { + case USR: + result.access_mask = + ((mode & S_IRUSR) ? r : 0 ) | + ((mode & S_IWUSR) ? w : 0 ) | + ((mode & S_IXUSR) ? x : 0 ); + if (lp_parm_bool(SNUM(conn), PARM_ONEFS_TYPE, -- Samba Shared Repository