From 4cf5769331bb9432fb7455f6eb0384b0282f605f Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Tue, 1 Aug 2006 07:38:36 +0000 Subject: r17353: Add support for JFS2 NFS4/AIXC and GPFS acls based on NFSv4 ACLs. (This used to be commit 72312cb2e255301f978455a559461ad83b13b6cb) --- source3/modules/nfs4_acls.c | 668 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 668 insertions(+) create mode 100644 source3/modules/nfs4_acls.c (limited to 'source3/modules/nfs4_acls.c') diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c new file mode 100644 index 0000000000..5daab41b45 --- /dev/null +++ b/source3/modules/nfs4_acls.c @@ -0,0 +1,668 @@ +/* + * NFS4 ACL handling + * + * Copyright (C) Jim McDonough, 2006 + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" +#include "nfs4_acls.h" + +#define SMBACL4_PARAM_TYPE_NAME "nfs4" + +#define SMB_ACE4_INT_MAGIC 0x76F8A967 +typedef struct _SMB_ACE4_INT_T +{ + uint32 magic; + SMB_ACE4PROP_T prop; + void *next; +} SMB_ACE4_INT_T; + +#define SMB_ACL4_INT_MAGIC 0x29A3E792 +typedef struct _SMB_ACL4_INT_T +{ + uint32 magic; + uint32 naces; + SMB_ACE4_INT_T *first; + SMB_ACE4_INT_T *last; +} SMB_ACL4_INT_T; + +extern struct current_user current_user; +extern int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid); +extern BOOL unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, + uint32 security_info_sent, SEC_DESC *psd); + +static SMB_ACL4_INT_T *get_validated_aclint(SMB4ACL_T *acl) +{ + SMB_ACL4_INT_T *aclint = (SMB_ACL4_INT_T *)acl; + if (acl==NULL) + { + DEBUG(2, ("acl is NULL\n")); + errno = EINVAL; + return NULL; + } + if (aclint->magic!=SMB_ACL4_INT_MAGIC) + { + DEBUG(2, ("aclint bad magic 0x%x\n", aclint->magic)); + errno = EINVAL; + return NULL; + } + return aclint; +} + +static SMB_ACE4_INT_T *get_validated_aceint(SMB4ACE_T *ace) +{ + SMB_ACE4_INT_T *aceint = (SMB_ACE4_INT_T *)ace; + if (ace==NULL) + { + DEBUG(2, ("ace is NULL\n")); + errno = EINVAL; + return NULL; + } + if (aceint->magic!=SMB_ACE4_INT_MAGIC) + { + DEBUG(2, ("aceint bad magic 0x%x\n", aceint->magic)); + errno = EINVAL; + return NULL; + } + return aceint; +} + +SMB4ACL_T *smb_create_smb4acl(void) +{ + TALLOC_CTX *mem_ctx = main_loop_talloc_get(); + SMB_ACL4_INT_T *acl = (SMB_ACL4_INT_T *)talloc_size(mem_ctx, sizeof(SMB_ACL4_INT_T)); + if (acl==NULL) + { + DEBUG(0, ("talloc_size failed\n")); + errno = ENOMEM; + return NULL; + } + memset(acl, 0, sizeof(SMB_ACL4_INT_T)); + acl->magic = SMB_ACL4_INT_MAGIC; + /* acl->first, last = NULL not needed */ + return (SMB4ACL_T *)acl; +} + +SMB4ACE_T *smb_add_ace4(SMB4ACL_T *acl, SMB_ACE4PROP_T *prop) +{ + SMB_ACL4_INT_T *aclint = get_validated_aclint(acl); + TALLOC_CTX *mem_ctx = main_loop_talloc_get(); + SMB_ACE4_INT_T *ace; + + ace = (SMB_ACE4_INT_T *)talloc_size(mem_ctx, sizeof(SMB_ACE4_INT_T)); + if (ace==NULL) + { + DEBUG(0, ("talloc_size failed\n")); + errno = ENOMEM; + return NULL; + } + memset(ace, 0, sizeof(SMB_ACE4_INT_T)); + ace->magic = SMB_ACE4_INT_MAGIC; + /* ace->next = NULL not needed */ + memcpy(&ace->prop, prop, sizeof(SMB_ACE4PROP_T)); + + if (aclint->first==NULL) + { + aclint->first = ace; + aclint->last = ace; + } else { + aclint->last->next = (void *)ace; + aclint->last = ace; + } + aclint->naces++; + + return (SMB4ACE_T *)ace; +} + +SMB_ACE4PROP_T *smb_get_ace4(SMB4ACE_T *ace) +{ + SMB_ACE4_INT_T *aceint = get_validated_aceint(ace); + if (aceint==NULL) + return NULL; + + return &aceint->prop; +} + +SMB4ACE_T *smb_next_ace4(SMB4ACE_T *ace) +{ + SMB_ACE4_INT_T *aceint = get_validated_aceint(ace); + if (aceint==NULL) + return NULL; + + return (SMB4ACE_T *)aceint->next; +} + +SMB4ACE_T *smb_first_ace4(SMB4ACL_T *acl) +{ + SMB_ACL4_INT_T *aclint = get_validated_aclint(acl); + if (aclint==NULL) + return NULL; + + return (SMB4ACE_T *)aclint->first; +} + +uint32 smb_get_naces(SMB4ACL_T *acl) +{ + SMB_ACL4_INT_T *aclint = get_validated_aclint(acl); + if (aclint==NULL) + return 0; + + return aclint->naces; +} + +static int smbacl4_GetFileOwner(files_struct *fsp, SMB_STRUCT_STAT *psbuf) +{ + memset(psbuf, 0, sizeof(SMB_STRUCT_STAT)); + if (fsp->is_directory || fsp->fh->fd == -1) { + /* Get the stat struct for the owner info. */ + if (SMB_VFS_STAT(fsp->conn,fsp->fsp_name, psbuf) != 0) + { + DEBUG(8, ("SMB_VFS_STAT failed with error %s\n", + strerror(errno))); + return -1; + } + } else { + if (SMB_VFS_FSTAT(fsp,fsp->fh->fd, psbuf) != 0) + { + DEBUG(8, ("SMB_VFS_FSTAT failed with error %s\n", + strerror(errno))); + return -1; + } + } + + return 0; +} + +static BOOL smbacl4_nfs42win(SMB4ACL_T *acl, /* in */ + DOM_SID *psid_owner, /* in */ + DOM_SID *psid_group, /* in */ + SEC_ACE **ppnt_ace_list, /* out */ + int *pgood_aces /* out */ +) +{ + SMB_ACL4_INT_T *aclint = (SMB_ACL4_INT_T *)acl; + SMB_ACE4_INT_T *aceint; + SEC_ACE *nt_ace_list = NULL; + int good_aces = 0; + TALLOC_CTX *mem_ctx = main_loop_talloc_get(); + + DEBUG(10, ("smbacl_nfs42win entered")); + + aclint = get_validated_aclint(acl); + if (aclint==NULL) + return False; + + nt_ace_list = (SEC_ACE *)talloc_size(mem_ctx, aclint->naces * sizeof(SEC_ACE)); + if (nt_ace_list==NULL) + { + DEBUG(10, ("talloc error")); + errno = ENOMEM; + return False; + } + memset(nt_ace_list, 0, aclint->naces * sizeof(SEC_ACE)); + + for (aceint=aclint->first; aceint!=NULL; aceint=(SMB_ACE4_INT_T *)aceint->next) { + SEC_ACCESS mask; + DOM_SID sid; + SMB_ACE4PROP_T *ace = &aceint->prop; + + DEBUG(10, ("magic: 0x%x, type: %d, iflags: %x, flags: %x, mask: %x, " + "who: %d\n", aceint->magic, ace->aceType, ace->flags, + ace->aceFlags, ace->aceMask, ace->who.id)); + + SMB_ASSERT(aceint->magic==SMB_ACE4_INT_MAGIC); + + if (ace->flags & SMB_ACE4_ID_SPECIAL) { + switch (ace->who.special_id) { + case SMB_ACE4_WHO_OWNER: + sid_copy(&sid, psid_owner); + break; + case SMB_ACE4_WHO_GROUP: + sid_copy(&sid, psid_group); + break; + case SMB_ACE4_WHO_EVERYONE: + sid_copy(&sid, &global_sid_World); + break; + default: + DEBUG(8, ("invalid special who id %d " + "ignored\n", ace->who.special_id)); + } + } else { + if (ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) { + gid_to_sid(&sid, ace->who.gid); + } else { + uid_to_sid(&sid, ace->who.uid); + } + } + DEBUG(10, ("mapped %d to %s\n", ace->who.id, + sid_string_static(&sid))); + + init_sec_access(&mask, ace->aceMask); + init_sec_ace(&nt_ace_list[good_aces++], &sid, + ace->aceType, mask, + ace->aceFlags & 0xf); + } + + *ppnt_ace_list = nt_ace_list; + *pgood_aces = good_aces; + + return True; +} + +size_t smb_get_nt_acl_nfs4(files_struct *fsp, + uint32 security_info, + SEC_DESC **ppdesc, SMB4ACL_T *acl) +{ + int good_aces = 0; + SMB_STRUCT_STAT sbuf; + DOM_SID sid_owner, sid_group; + size_t sd_size = 0; + SEC_ACE *nt_ace_list = NULL; + SEC_ACL *psa = NULL; + TALLOC_CTX *mem_ctx = main_loop_talloc_get(); + + DEBUG(10, ("smb_get_nt_acl_nfs4 invoked for %s\n", fsp->fsp_name)); + + if (acl==NULL || smb_get_naces(acl)==0) + return 0; /* special because we shouldn't alloc 0 for win */ + + if (smbacl4_GetFileOwner(fsp, &sbuf)) + return 0; + + uid_to_sid(&sid_owner, sbuf.st_uid); + gid_to_sid(&sid_group, sbuf.st_gid); + + if (smbacl4_nfs42win(acl, + &sid_owner, + &sid_group, + &nt_ace_list, + &good_aces + )==False) { + DEBUG(8,("smbacl4_nfs42win failed\n")); + return 0; + } + + psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, + good_aces, nt_ace_list); + if (psa == NULL) { + DEBUG(2,("make_sec_acl failed\n")); + return 0; + } + + DEBUG(10,("after make sec_acl\n")); + *ppdesc = make_sec_desc(mem_ctx, SEC_DESC_REVISION, + SEC_DESC_SELF_RELATIVE, + (security_info & OWNER_SECURITY_INFORMATION) + ? &sid_owner : NULL, + (security_info & GROUP_SECURITY_INFORMATION) + ? &sid_group : NULL, + NULL, psa, &sd_size); + if (*ppdesc==NULL) { + DEBUG(2,("make_sec_desc failed\n")); + return 0; + } + + DEBUG(10, ("smb_get_nt_acl_nfs4 successfully exited with sd_size %d\n", sd_size)); + return sd_size; +} + +enum smbacl4_mode_enum {e_simple=0, e_special=1}; +enum smbacl4_acedup_enum {e_dontcare=0, e_reject=1, e_ignore=2, e_merge=3}; + +typedef struct _smbacl4_vfs_params { + enum smbacl4_mode_enum mode; + BOOL do_chown; + enum smbacl4_acedup_enum acedup; +} smbacl4_vfs_params; + +/* + * Gather special parameters for NFS4 ACL handling + */ +static int smbacl4_get_vfs_params( + const char *type_name, + files_struct *fsp, + smbacl4_vfs_params *params +) +{ + static const struct enum_list enum_smbacl4_modes[] = { + { e_simple, "simple" }, + { e_special, "special" } + }; + static const struct enum_list enum_smbacl4_acedups[] = { + { e_dontcare, "dontcare" }, + { e_reject, "reject" }, + { e_ignore, "ignore" }, + { e_merge, "merge" }, + }; + + memset(params, 0, sizeof(smbacl4_vfs_params)); + params->mode = (enum smbacl4_mode_enum)lp_parm_enum( + SNUM(fsp->conn), type_name, + "mode", enum_smbacl4_modes, e_simple); + params->do_chown = lp_parm_bool(SNUM(fsp->conn), type_name, + "chown", True); + params->acedup = (enum smbacl4_acedup_enum)lp_parm_enum( + SNUM(fsp->conn), type_name, + "acedup", enum_smbacl4_acedups, e_dontcare); + + DEBUG(10, ("mode:%s, do_chown:%s, acedup: %s\n", + enum_smbacl4_modes[params->mode].name, + params->do_chown ? "true" : "false", + enum_smbacl4_acedups[params->acedup].name)); + + return 0; +} + +static void smbacl4_dump_nfs4acl(int level, SMB4ACL_T *acl) +{ + SMB_ACL4_INT_T *aclint = get_validated_aclint(acl); + SMB_ACE4_INT_T *aceint; + + DEBUG(level, ("NFS4ACL: size=%d\n", aclint->naces)); + + for(aceint = aclint->first; aceint!=NULL; aceint=(SMB_ACE4_INT_T *)aceint->next) { + SMB_ACE4PROP_T *ace = &aceint->prop; + + DEBUG(level, ("\tACE: type=%d, flags=0x%x, fflags=0x%x, mask=0x%x, id=%d\n", + ace->aceType, + ace->aceFlags, ace->flags, + ace->aceMask, + ace->who.id)); + } +} + +/* + * Find 2 NFS4 who-special ACE property (non-copy!!!) + * match nonzero if "special" and who is equal + * return ace if found matching; otherwise NULL + */ +static SMB_ACE4PROP_T *smbacl4_find_equal_special( + SMB4ACL_T *acl, + SMB_ACE4PROP_T *aceNew) +{ + SMB_ACL4_INT_T *aclint = get_validated_aclint(acl); + SMB_ACE4_INT_T *aceint; + + for(aceint = aclint->first; aceint!=NULL; aceint=(SMB_ACE4_INT_T *)aceint->next) { + SMB_ACE4PROP_T *ace = &aceint->prop; + + if (ace->flags == aceNew->flags && + ace->aceType==aceNew->aceType && + (ace->aceFlags&SMB_ACE4_IDENTIFIER_GROUP)== + (aceNew->aceFlags&SMB_ACE4_IDENTIFIER_GROUP) + ) { + /* keep type safety; e.g. gid is an u.short */ + if (ace->flags & SMB_ACE4_ID_SPECIAL) + { + if (ace->who.special_id==aceNew->who.special_id) + return ace; + } else { + if (ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) + { + if (ace->who.gid==aceNew->who.gid) + return ace; + } else { + if (ace->who.uid==aceNew->who.uid) + return ace; + } + } + } + } + + return NULL; +} + +static int smbacl4_fill_ace4( + TALLOC_CTX *mem_ctx, + smbacl4_vfs_params *params, + uid_t ownerUID, + gid_t ownerGID, + SEC_ACE *ace_nt, /* input */ + SMB_ACE4PROP_T *ace_v4 /* output */ +) +{ + const char *dom, *name; + enum SID_NAME_USE type; + uid_t uid; + gid_t gid; + + DEBUG(10, ("got ace for %s\n", + sid_string_static(&ace_nt->trustee))); + + memset(ace_v4, 0, sizeof(SMB_ACE4PROP_T)); + ace_v4->aceType = ace_nt->type; /* only ACCES|DENY supported right now */ + ace_v4->aceFlags = ace_nt->flags & SEC_ACE_FLAG_VALID_INHERIT; + ace_v4->aceMask = ace_nt->info.mask & + (STD_RIGHT_ALL_ACCESS | SA_RIGHT_FILE_ALL_ACCESS); + + if (ace_v4->aceFlags!=ace_nt->flags) + DEBUG(9, ("ace_v4->aceFlags(0x%x)!=ace_nt->flags(0x%x)\n", + ace_v4->aceFlags, ace_nt->flags)); + + if (ace_v4->aceMask!=ace_nt->info.mask) + DEBUG(9, ("ace_v4->aceMask(0x%x)!=ace_nt->info.mask(0x%x)\n", + ace_v4->aceMask, ace_nt->info.mask)); + + if (sid_equal(&ace_nt->trustee, &global_sid_World)) { + ace_v4->who.special_id = SMB_ACE4_WHO_EVERYONE; + ace_v4->flags |= SMB_ACE4_ID_SPECIAL; + } else { + if (!lookup_sid(mem_ctx, &ace_nt->trustee, &dom, &name, &type)) { + DEBUG(8, ("Could not find %s' type\n", + sid_string_static(&ace_nt->trustee))); + errno = EINVAL; + return -1; + } + + if (type == SID_NAME_USER) { + if (!sid_to_uid(&ace_nt->trustee, &uid)) { + DEBUG(2, ("Could not convert %s to uid\n", + sid_string_static(&ace_nt->trustee))); + return -1; + } + + if (params->mode==e_special && uid==ownerUID) { + ace_v4->flags |= SMB_ACE4_ID_SPECIAL; + ace_v4->who.special_id = SMB_ACE4_WHO_OWNER; + } else { + ace_v4->who.uid = uid; + } + } else { /* else group? - TODO check it... */ + if (!sid_to_gid(&ace_nt->trustee, &gid)) { + DEBUG(2, ("Could not convert %s to gid\n", + sid_string_static(&ace_nt->trustee))); + return -1; + } + ace_v4->aceFlags |= SMB_ACE4_IDENTIFIER_GROUP; + + if (params->mode==e_special && gid==ownerGID) { + ace_v4->flags |= SMB_ACE4_ID_SPECIAL; + ace_v4->who.special_id = SMB_ACE4_WHO_GROUP; + } else { + ace_v4->who.gid = gid; + } + } + } + + return 0; /* OK */ +} + +static int smbacl4_MergeIgnoreReject( + enum smbacl4_acedup_enum acedup, + SMB4ACL_T *acl, /* may modify it */ + SMB_ACE4PROP_T *ace, /* the "new" ACE */ + BOOL *paddNewACE, + int i +) +{ + int result = 0; + SMB_ACE4PROP_T *ace4found = smbacl4_find_equal_special(acl, ace); + if (ace4found) + { + switch(acedup) + { + case e_merge: /* "merge" flags */ + *paddNewACE = False; + ace4found->aceFlags |= ace->aceFlags; + ace4found->aceMask |= ace->aceMask; + break; + case e_ignore: /* leave out this record */ + *paddNewACE = False; + break; + case e_reject: /* do an error */ + DEBUG(8, ("ACL rejected by duplicate nt ace#%d\n", i)); + errno = EINVAL; /* SHOULD be set on any _real_ error */ + result = -1; + break; + default: + break; + } + } + return result; +} + +static SMB4ACL_T *smbacl4_win2nfs4( + SEC_ACL *dacl, + smbacl4_vfs_params *pparams, + uid_t ownerUID, + gid_t ownerGID +) +{ + SMB4ACL_T *acl; + uint32 i; + TALLOC_CTX *mem_ctx = main_loop_talloc_get(); + + DEBUG(10, ("smbacl4_win2nfs4 invoked\n")); + + acl = smb_create_smb4acl(); + if (acl==NULL) + return NULL; + + for(i=0; inum_aces; i++) { + SMB_ACE4PROP_T ace_v4; + BOOL addNewACE = True; + + if (smbacl4_fill_ace4(mem_ctx, pparams, ownerUID, ownerGID, + dacl->ace + i, &ace_v4)) + return NULL; + + if (pparams->acedup!=e_dontcare) { + if (smbacl4_MergeIgnoreReject(pparams->acedup, acl, + &ace_v4, &addNewACE, i)) + return NULL; + } + + if (addNewACE) + smb_add_ace4(acl, &ace_v4); + } + + return acl; +} + +BOOL smb_set_nt_acl_nfs4(files_struct *fsp, + uint32 security_info_sent, + SEC_DESC *psd, + set_nfs4acl_native_fn_t set_nfs4_native) +{ + smbacl4_vfs_params params; + SMB4ACL_T *acl = NULL; + BOOL result; + + SMB_STRUCT_STAT sbuf; + BOOL need_chown = False; + uid_t newUID = (uid_t)-1; + gid_t newGID = (gid_t)-1; + + DEBUG(10, ("smb_set_nt_acl_nfs4 invoked for %s\n", fsp->fsp_name)); + + if ((security_info_sent & (DACL_SECURITY_INFORMATION | + GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION)) == 0) + { + DEBUG(9, ("security_info_sent (0x%x) ignored\n", + security_info_sent)); + return True; /* won't show error - later to be refined... */ + } + + /* Special behaviours */ + if (smbacl4_get_vfs_params(SMBACL4_PARAM_TYPE_NAME, fsp, ¶ms)) + return False; + + if (smbacl4_GetFileOwner(fsp, &sbuf)) + return False; + + /* chown logic is a copy/paste from posix_acl.c:set_nt_acl */ + if (!unpack_nt_owners(SNUM(fsp->conn), &newUID, &newGID, security_info_sent, psd)) + { + DEBUG(8, ("unpack_nt_owners failed")); + return False; + } + if (((newUID != (uid_t)-1) && (sbuf.st_uid != newUID)) || + ((newGID != (gid_t)-1) && (sbuf.st_gid != newGID))) { + need_chown = True; + } + if (need_chown) { + if ((newUID == (uid_t)-1 || newUID == current_user.ut.uid)) { + if(try_chown(fsp->conn, fsp->fsp_name, newUID, newGID)) { + DEBUG(3,("chown %s, %u, %u failed. Error = %s.\n", + fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID, strerror(errno) )); + return False; + } + DEBUG(10,("chown %s, %u, %u succeeded.\n", + fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID)); + if (smbacl4_GetFileOwner(fsp, &sbuf)) + return False; + need_chown = False; + } else { /* chown is needed, but _after_ changing acl */ + sbuf.st_uid = newUID; /* OWNER@ in case of e_special */ + sbuf.st_gid = newGID; /* GROUP@ in case of e_special */ + } + } + + if ((security_info_sent & DACL_SECURITY_INFORMATION)!=0 && psd->dacl!=NULL) + { + acl = smbacl4_win2nfs4(psd->dacl, ¶ms, sbuf.st_uid, sbuf.st_gid); + if (!acl) + return False; + + smbacl4_dump_nfs4acl(10, acl); + + result = set_nfs4_native(fsp, acl); + if (result!=True) + { + DEBUG(10, ("set_nfs4_native failed with %s\n", strerror(errno))); + return False; + } + } else + DEBUG(10, ("no dacl found; security_info_sent = 0x%x\n", security_info_sent)); + + /* Any chown pending? */ + if (need_chown) { + DEBUG(3,("chown#2 %s. uid = %u, gid = %u.\n", + fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID)); + if (try_chown(fsp->conn, fsp->fsp_name, newUID, newGID)) { + DEBUG(2,("chown#2 %s, %u, %u failed. Error = %s.\n", + fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID, + strerror(errno))); + return False; + } + DEBUG(10,("chown#2 %s, %u, %u succeeded.\n", + fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID)); + } + + DEBUG(10, ("smb_set_nt_acl_nfs4 succeeded\n")); + return True; +} -- cgit From 16bf23d973b899f570b6793cf52507086d74d66a Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Tue, 1 Aug 2006 08:27:19 +0000 Subject: r17354: Revert -r 17353 per Volker request while gpfs compatibility layer code will be released. (This used to be commit 5b1db0151461af18d994359e86c649922fc6de65) --- source3/modules/nfs4_acls.c | 668 -------------------------------------------- 1 file changed, 668 deletions(-) (limited to 'source3/modules/nfs4_acls.c') diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index 5daab41b45..e69de29bb2 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -1,668 +0,0 @@ -/* - * NFS4 ACL handling - * - * Copyright (C) Jim McDonough, 2006 - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "includes.h" -#include "nfs4_acls.h" - -#define SMBACL4_PARAM_TYPE_NAME "nfs4" - -#define SMB_ACE4_INT_MAGIC 0x76F8A967 -typedef struct _SMB_ACE4_INT_T -{ - uint32 magic; - SMB_ACE4PROP_T prop; - void *next; -} SMB_ACE4_INT_T; - -#define SMB_ACL4_INT_MAGIC 0x29A3E792 -typedef struct _SMB_ACL4_INT_T -{ - uint32 magic; - uint32 naces; - SMB_ACE4_INT_T *first; - SMB_ACE4_INT_T *last; -} SMB_ACL4_INT_T; - -extern struct current_user current_user; -extern int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid); -extern BOOL unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, - uint32 security_info_sent, SEC_DESC *psd); - -static SMB_ACL4_INT_T *get_validated_aclint(SMB4ACL_T *acl) -{ - SMB_ACL4_INT_T *aclint = (SMB_ACL4_INT_T *)acl; - if (acl==NULL) - { - DEBUG(2, ("acl is NULL\n")); - errno = EINVAL; - return NULL; - } - if (aclint->magic!=SMB_ACL4_INT_MAGIC) - { - DEBUG(2, ("aclint bad magic 0x%x\n", aclint->magic)); - errno = EINVAL; - return NULL; - } - return aclint; -} - -static SMB_ACE4_INT_T *get_validated_aceint(SMB4ACE_T *ace) -{ - SMB_ACE4_INT_T *aceint = (SMB_ACE4_INT_T *)ace; - if (ace==NULL) - { - DEBUG(2, ("ace is NULL\n")); - errno = EINVAL; - return NULL; - } - if (aceint->magic!=SMB_ACE4_INT_MAGIC) - { - DEBUG(2, ("aceint bad magic 0x%x\n", aceint->magic)); - errno = EINVAL; - return NULL; - } - return aceint; -} - -SMB4ACL_T *smb_create_smb4acl(void) -{ - TALLOC_CTX *mem_ctx = main_loop_talloc_get(); - SMB_ACL4_INT_T *acl = (SMB_ACL4_INT_T *)talloc_size(mem_ctx, sizeof(SMB_ACL4_INT_T)); - if (acl==NULL) - { - DEBUG(0, ("talloc_size failed\n")); - errno = ENOMEM; - return NULL; - } - memset(acl, 0, sizeof(SMB_ACL4_INT_T)); - acl->magic = SMB_ACL4_INT_MAGIC; - /* acl->first, last = NULL not needed */ - return (SMB4ACL_T *)acl; -} - -SMB4ACE_T *smb_add_ace4(SMB4ACL_T *acl, SMB_ACE4PROP_T *prop) -{ - SMB_ACL4_INT_T *aclint = get_validated_aclint(acl); - TALLOC_CTX *mem_ctx = main_loop_talloc_get(); - SMB_ACE4_INT_T *ace; - - ace = (SMB_ACE4_INT_T *)talloc_size(mem_ctx, sizeof(SMB_ACE4_INT_T)); - if (ace==NULL) - { - DEBUG(0, ("talloc_size failed\n")); - errno = ENOMEM; - return NULL; - } - memset(ace, 0, sizeof(SMB_ACE4_INT_T)); - ace->magic = SMB_ACE4_INT_MAGIC; - /* ace->next = NULL not needed */ - memcpy(&ace->prop, prop, sizeof(SMB_ACE4PROP_T)); - - if (aclint->first==NULL) - { - aclint->first = ace; - aclint->last = ace; - } else { - aclint->last->next = (void *)ace; - aclint->last = ace; - } - aclint->naces++; - - return (SMB4ACE_T *)ace; -} - -SMB_ACE4PROP_T *smb_get_ace4(SMB4ACE_T *ace) -{ - SMB_ACE4_INT_T *aceint = get_validated_aceint(ace); - if (aceint==NULL) - return NULL; - - return &aceint->prop; -} - -SMB4ACE_T *smb_next_ace4(SMB4ACE_T *ace) -{ - SMB_ACE4_INT_T *aceint = get_validated_aceint(ace); - if (aceint==NULL) - return NULL; - - return (SMB4ACE_T *)aceint->next; -} - -SMB4ACE_T *smb_first_ace4(SMB4ACL_T *acl) -{ - SMB_ACL4_INT_T *aclint = get_validated_aclint(acl); - if (aclint==NULL) - return NULL; - - return (SMB4ACE_T *)aclint->first; -} - -uint32 smb_get_naces(SMB4ACL_T *acl) -{ - SMB_ACL4_INT_T *aclint = get_validated_aclint(acl); - if (aclint==NULL) - return 0; - - return aclint->naces; -} - -static int smbacl4_GetFileOwner(files_struct *fsp, SMB_STRUCT_STAT *psbuf) -{ - memset(psbuf, 0, sizeof(SMB_STRUCT_STAT)); - if (fsp->is_directory || fsp->fh->fd == -1) { - /* Get the stat struct for the owner info. */ - if (SMB_VFS_STAT(fsp->conn,fsp->fsp_name, psbuf) != 0) - { - DEBUG(8, ("SMB_VFS_STAT failed with error %s\n", - strerror(errno))); - return -1; - } - } else { - if (SMB_VFS_FSTAT(fsp,fsp->fh->fd, psbuf) != 0) - { - DEBUG(8, ("SMB_VFS_FSTAT failed with error %s\n", - strerror(errno))); - return -1; - } - } - - return 0; -} - -static BOOL smbacl4_nfs42win(SMB4ACL_T *acl, /* in */ - DOM_SID *psid_owner, /* in */ - DOM_SID *psid_group, /* in */ - SEC_ACE **ppnt_ace_list, /* out */ - int *pgood_aces /* out */ -) -{ - SMB_ACL4_INT_T *aclint = (SMB_ACL4_INT_T *)acl; - SMB_ACE4_INT_T *aceint; - SEC_ACE *nt_ace_list = NULL; - int good_aces = 0; - TALLOC_CTX *mem_ctx = main_loop_talloc_get(); - - DEBUG(10, ("smbacl_nfs42win entered")); - - aclint = get_validated_aclint(acl); - if (aclint==NULL) - return False; - - nt_ace_list = (SEC_ACE *)talloc_size(mem_ctx, aclint->naces * sizeof(SEC_ACE)); - if (nt_ace_list==NULL) - { - DEBUG(10, ("talloc error")); - errno = ENOMEM; - return False; - } - memset(nt_ace_list, 0, aclint->naces * sizeof(SEC_ACE)); - - for (aceint=aclint->first; aceint!=NULL; aceint=(SMB_ACE4_INT_T *)aceint->next) { - SEC_ACCESS mask; - DOM_SID sid; - SMB_ACE4PROP_T *ace = &aceint->prop; - - DEBUG(10, ("magic: 0x%x, type: %d, iflags: %x, flags: %x, mask: %x, " - "who: %d\n", aceint->magic, ace->aceType, ace->flags, - ace->aceFlags, ace->aceMask, ace->who.id)); - - SMB_ASSERT(aceint->magic==SMB_ACE4_INT_MAGIC); - - if (ace->flags & SMB_ACE4_ID_SPECIAL) { - switch (ace->who.special_id) { - case SMB_ACE4_WHO_OWNER: - sid_copy(&sid, psid_owner); - break; - case SMB_ACE4_WHO_GROUP: - sid_copy(&sid, psid_group); - break; - case SMB_ACE4_WHO_EVERYONE: - sid_copy(&sid, &global_sid_World); - break; - default: - DEBUG(8, ("invalid special who id %d " - "ignored\n", ace->who.special_id)); - } - } else { - if (ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) { - gid_to_sid(&sid, ace->who.gid); - } else { - uid_to_sid(&sid, ace->who.uid); - } - } - DEBUG(10, ("mapped %d to %s\n", ace->who.id, - sid_string_static(&sid))); - - init_sec_access(&mask, ace->aceMask); - init_sec_ace(&nt_ace_list[good_aces++], &sid, - ace->aceType, mask, - ace->aceFlags & 0xf); - } - - *ppnt_ace_list = nt_ace_list; - *pgood_aces = good_aces; - - return True; -} - -size_t smb_get_nt_acl_nfs4(files_struct *fsp, - uint32 security_info, - SEC_DESC **ppdesc, SMB4ACL_T *acl) -{ - int good_aces = 0; - SMB_STRUCT_STAT sbuf; - DOM_SID sid_owner, sid_group; - size_t sd_size = 0; - SEC_ACE *nt_ace_list = NULL; - SEC_ACL *psa = NULL; - TALLOC_CTX *mem_ctx = main_loop_talloc_get(); - - DEBUG(10, ("smb_get_nt_acl_nfs4 invoked for %s\n", fsp->fsp_name)); - - if (acl==NULL || smb_get_naces(acl)==0) - return 0; /* special because we shouldn't alloc 0 for win */ - - if (smbacl4_GetFileOwner(fsp, &sbuf)) - return 0; - - uid_to_sid(&sid_owner, sbuf.st_uid); - gid_to_sid(&sid_group, sbuf.st_gid); - - if (smbacl4_nfs42win(acl, - &sid_owner, - &sid_group, - &nt_ace_list, - &good_aces - )==False) { - DEBUG(8,("smbacl4_nfs42win failed\n")); - return 0; - } - - psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, - good_aces, nt_ace_list); - if (psa == NULL) { - DEBUG(2,("make_sec_acl failed\n")); - return 0; - } - - DEBUG(10,("after make sec_acl\n")); - *ppdesc = make_sec_desc(mem_ctx, SEC_DESC_REVISION, - SEC_DESC_SELF_RELATIVE, - (security_info & OWNER_SECURITY_INFORMATION) - ? &sid_owner : NULL, - (security_info & GROUP_SECURITY_INFORMATION) - ? &sid_group : NULL, - NULL, psa, &sd_size); - if (*ppdesc==NULL) { - DEBUG(2,("make_sec_desc failed\n")); - return 0; - } - - DEBUG(10, ("smb_get_nt_acl_nfs4 successfully exited with sd_size %d\n", sd_size)); - return sd_size; -} - -enum smbacl4_mode_enum {e_simple=0, e_special=1}; -enum smbacl4_acedup_enum {e_dontcare=0, e_reject=1, e_ignore=2, e_merge=3}; - -typedef struct _smbacl4_vfs_params { - enum smbacl4_mode_enum mode; - BOOL do_chown; - enum smbacl4_acedup_enum acedup; -} smbacl4_vfs_params; - -/* - * Gather special parameters for NFS4 ACL handling - */ -static int smbacl4_get_vfs_params( - const char *type_name, - files_struct *fsp, - smbacl4_vfs_params *params -) -{ - static const struct enum_list enum_smbacl4_modes[] = { - { e_simple, "simple" }, - { e_special, "special" } - }; - static const struct enum_list enum_smbacl4_acedups[] = { - { e_dontcare, "dontcare" }, - { e_reject, "reject" }, - { e_ignore, "ignore" }, - { e_merge, "merge" }, - }; - - memset(params, 0, sizeof(smbacl4_vfs_params)); - params->mode = (enum smbacl4_mode_enum)lp_parm_enum( - SNUM(fsp->conn), type_name, - "mode", enum_smbacl4_modes, e_simple); - params->do_chown = lp_parm_bool(SNUM(fsp->conn), type_name, - "chown", True); - params->acedup = (enum smbacl4_acedup_enum)lp_parm_enum( - SNUM(fsp->conn), type_name, - "acedup", enum_smbacl4_acedups, e_dontcare); - - DEBUG(10, ("mode:%s, do_chown:%s, acedup: %s\n", - enum_smbacl4_modes[params->mode].name, - params->do_chown ? "true" : "false", - enum_smbacl4_acedups[params->acedup].name)); - - return 0; -} - -static void smbacl4_dump_nfs4acl(int level, SMB4ACL_T *acl) -{ - SMB_ACL4_INT_T *aclint = get_validated_aclint(acl); - SMB_ACE4_INT_T *aceint; - - DEBUG(level, ("NFS4ACL: size=%d\n", aclint->naces)); - - for(aceint = aclint->first; aceint!=NULL; aceint=(SMB_ACE4_INT_T *)aceint->next) { - SMB_ACE4PROP_T *ace = &aceint->prop; - - DEBUG(level, ("\tACE: type=%d, flags=0x%x, fflags=0x%x, mask=0x%x, id=%d\n", - ace->aceType, - ace->aceFlags, ace->flags, - ace->aceMask, - ace->who.id)); - } -} - -/* - * Find 2 NFS4 who-special ACE property (non-copy!!!) - * match nonzero if "special" and who is equal - * return ace if found matching; otherwise NULL - */ -static SMB_ACE4PROP_T *smbacl4_find_equal_special( - SMB4ACL_T *acl, - SMB_ACE4PROP_T *aceNew) -{ - SMB_ACL4_INT_T *aclint = get_validated_aclint(acl); - SMB_ACE4_INT_T *aceint; - - for(aceint = aclint->first; aceint!=NULL; aceint=(SMB_ACE4_INT_T *)aceint->next) { - SMB_ACE4PROP_T *ace = &aceint->prop; - - if (ace->flags == aceNew->flags && - ace->aceType==aceNew->aceType && - (ace->aceFlags&SMB_ACE4_IDENTIFIER_GROUP)== - (aceNew->aceFlags&SMB_ACE4_IDENTIFIER_GROUP) - ) { - /* keep type safety; e.g. gid is an u.short */ - if (ace->flags & SMB_ACE4_ID_SPECIAL) - { - if (ace->who.special_id==aceNew->who.special_id) - return ace; - } else { - if (ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) - { - if (ace->who.gid==aceNew->who.gid) - return ace; - } else { - if (ace->who.uid==aceNew->who.uid) - return ace; - } - } - } - } - - return NULL; -} - -static int smbacl4_fill_ace4( - TALLOC_CTX *mem_ctx, - smbacl4_vfs_params *params, - uid_t ownerUID, - gid_t ownerGID, - SEC_ACE *ace_nt, /* input */ - SMB_ACE4PROP_T *ace_v4 /* output */ -) -{ - const char *dom, *name; - enum SID_NAME_USE type; - uid_t uid; - gid_t gid; - - DEBUG(10, ("got ace for %s\n", - sid_string_static(&ace_nt->trustee))); - - memset(ace_v4, 0, sizeof(SMB_ACE4PROP_T)); - ace_v4->aceType = ace_nt->type; /* only ACCES|DENY supported right now */ - ace_v4->aceFlags = ace_nt->flags & SEC_ACE_FLAG_VALID_INHERIT; - ace_v4->aceMask = ace_nt->info.mask & - (STD_RIGHT_ALL_ACCESS | SA_RIGHT_FILE_ALL_ACCESS); - - if (ace_v4->aceFlags!=ace_nt->flags) - DEBUG(9, ("ace_v4->aceFlags(0x%x)!=ace_nt->flags(0x%x)\n", - ace_v4->aceFlags, ace_nt->flags)); - - if (ace_v4->aceMask!=ace_nt->info.mask) - DEBUG(9, ("ace_v4->aceMask(0x%x)!=ace_nt->info.mask(0x%x)\n", - ace_v4->aceMask, ace_nt->info.mask)); - - if (sid_equal(&ace_nt->trustee, &global_sid_World)) { - ace_v4->who.special_id = SMB_ACE4_WHO_EVERYONE; - ace_v4->flags |= SMB_ACE4_ID_SPECIAL; - } else { - if (!lookup_sid(mem_ctx, &ace_nt->trustee, &dom, &name, &type)) { - DEBUG(8, ("Could not find %s' type\n", - sid_string_static(&ace_nt->trustee))); - errno = EINVAL; - return -1; - } - - if (type == SID_NAME_USER) { - if (!sid_to_uid(&ace_nt->trustee, &uid)) { - DEBUG(2, ("Could not convert %s to uid\n", - sid_string_static(&ace_nt->trustee))); - return -1; - } - - if (params->mode==e_special && uid==ownerUID) { - ace_v4->flags |= SMB_ACE4_ID_SPECIAL; - ace_v4->who.special_id = SMB_ACE4_WHO_OWNER; - } else { - ace_v4->who.uid = uid; - } - } else { /* else group? - TODO check it... */ - if (!sid_to_gid(&ace_nt->trustee, &gid)) { - DEBUG(2, ("Could not convert %s to gid\n", - sid_string_static(&ace_nt->trustee))); - return -1; - } - ace_v4->aceFlags |= SMB_ACE4_IDENTIFIER_GROUP; - - if (params->mode==e_special && gid==ownerGID) { - ace_v4->flags |= SMB_ACE4_ID_SPECIAL; - ace_v4->who.special_id = SMB_ACE4_WHO_GROUP; - } else { - ace_v4->who.gid = gid; - } - } - } - - return 0; /* OK */ -} - -static int smbacl4_MergeIgnoreReject( - enum smbacl4_acedup_enum acedup, - SMB4ACL_T *acl, /* may modify it */ - SMB_ACE4PROP_T *ace, /* the "new" ACE */ - BOOL *paddNewACE, - int i -) -{ - int result = 0; - SMB_ACE4PROP_T *ace4found = smbacl4_find_equal_special(acl, ace); - if (ace4found) - { - switch(acedup) - { - case e_merge: /* "merge" flags */ - *paddNewACE = False; - ace4found->aceFlags |= ace->aceFlags; - ace4found->aceMask |= ace->aceMask; - break; - case e_ignore: /* leave out this record */ - *paddNewACE = False; - break; - case e_reject: /* do an error */ - DEBUG(8, ("ACL rejected by duplicate nt ace#%d\n", i)); - errno = EINVAL; /* SHOULD be set on any _real_ error */ - result = -1; - break; - default: - break; - } - } - return result; -} - -static SMB4ACL_T *smbacl4_win2nfs4( - SEC_ACL *dacl, - smbacl4_vfs_params *pparams, - uid_t ownerUID, - gid_t ownerGID -) -{ - SMB4ACL_T *acl; - uint32 i; - TALLOC_CTX *mem_ctx = main_loop_talloc_get(); - - DEBUG(10, ("smbacl4_win2nfs4 invoked\n")); - - acl = smb_create_smb4acl(); - if (acl==NULL) - return NULL; - - for(i=0; inum_aces; i++) { - SMB_ACE4PROP_T ace_v4; - BOOL addNewACE = True; - - if (smbacl4_fill_ace4(mem_ctx, pparams, ownerUID, ownerGID, - dacl->ace + i, &ace_v4)) - return NULL; - - if (pparams->acedup!=e_dontcare) { - if (smbacl4_MergeIgnoreReject(pparams->acedup, acl, - &ace_v4, &addNewACE, i)) - return NULL; - } - - if (addNewACE) - smb_add_ace4(acl, &ace_v4); - } - - return acl; -} - -BOOL smb_set_nt_acl_nfs4(files_struct *fsp, - uint32 security_info_sent, - SEC_DESC *psd, - set_nfs4acl_native_fn_t set_nfs4_native) -{ - smbacl4_vfs_params params; - SMB4ACL_T *acl = NULL; - BOOL result; - - SMB_STRUCT_STAT sbuf; - BOOL need_chown = False; - uid_t newUID = (uid_t)-1; - gid_t newGID = (gid_t)-1; - - DEBUG(10, ("smb_set_nt_acl_nfs4 invoked for %s\n", fsp->fsp_name)); - - if ((security_info_sent & (DACL_SECURITY_INFORMATION | - GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION)) == 0) - { - DEBUG(9, ("security_info_sent (0x%x) ignored\n", - security_info_sent)); - return True; /* won't show error - later to be refined... */ - } - - /* Special behaviours */ - if (smbacl4_get_vfs_params(SMBACL4_PARAM_TYPE_NAME, fsp, ¶ms)) - return False; - - if (smbacl4_GetFileOwner(fsp, &sbuf)) - return False; - - /* chown logic is a copy/paste from posix_acl.c:set_nt_acl */ - if (!unpack_nt_owners(SNUM(fsp->conn), &newUID, &newGID, security_info_sent, psd)) - { - DEBUG(8, ("unpack_nt_owners failed")); - return False; - } - if (((newUID != (uid_t)-1) && (sbuf.st_uid != newUID)) || - ((newGID != (gid_t)-1) && (sbuf.st_gid != newGID))) { - need_chown = True; - } - if (need_chown) { - if ((newUID == (uid_t)-1 || newUID == current_user.ut.uid)) { - if(try_chown(fsp->conn, fsp->fsp_name, newUID, newGID)) { - DEBUG(3,("chown %s, %u, %u failed. Error = %s.\n", - fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID, strerror(errno) )); - return False; - } - DEBUG(10,("chown %s, %u, %u succeeded.\n", - fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID)); - if (smbacl4_GetFileOwner(fsp, &sbuf)) - return False; - need_chown = False; - } else { /* chown is needed, but _after_ changing acl */ - sbuf.st_uid = newUID; /* OWNER@ in case of e_special */ - sbuf.st_gid = newGID; /* GROUP@ in case of e_special */ - } - } - - if ((security_info_sent & DACL_SECURITY_INFORMATION)!=0 && psd->dacl!=NULL) - { - acl = smbacl4_win2nfs4(psd->dacl, ¶ms, sbuf.st_uid, sbuf.st_gid); - if (!acl) - return False; - - smbacl4_dump_nfs4acl(10, acl); - - result = set_nfs4_native(fsp, acl); - if (result!=True) - { - DEBUG(10, ("set_nfs4_native failed with %s\n", strerror(errno))); - return False; - } - } else - DEBUG(10, ("no dacl found; security_info_sent = 0x%x\n", security_info_sent)); - - /* Any chown pending? */ - if (need_chown) { - DEBUG(3,("chown#2 %s. uid = %u, gid = %u.\n", - fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID)); - if (try_chown(fsp->conn, fsp->fsp_name, newUID, newGID)) { - DEBUG(2,("chown#2 %s, %u, %u failed. Error = %s.\n", - fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID, - strerror(errno))); - return False; - } - DEBUG(10,("chown#2 %s, %u, %u succeeded.\n", - fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID)); - } - - DEBUG(10, ("smb_set_nt_acl_nfs4 succeeded\n")); - return True; -} -- cgit From fbd04d65c56c36bec287f6c4ffe84ea79b048fa7 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Tue, 1 Aug 2006 09:25:24 +0000 Subject: r17358: Re-add JFS2 NFS4 ACLs support, move readme for it into AIX-specific examples directory. (This used to be commit c085355c323c65ee782516859eed8a76b53e6035) --- source3/modules/nfs4_acls.c | 668 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 668 insertions(+) (limited to 'source3/modules/nfs4_acls.c') diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index e69de29bb2..795afee45a 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -0,0 +1,668 @@ +/* + * NFS4 ACL handling + * + * Copyright (C) Jim McDonough, 2006 + * Major code contributions from Peter Somogyi, somogyi@de.ibm.com + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" +#include "nfs4_acls.h" + +#define SMBACL4_PARAM_TYPE_NAME "nfs4" + +#define SMB_ACE4_INT_MAGIC 0x76F8A967 +typedef struct _SMB_ACE4_INT_T +{ + uint32 magic; + SMB_ACE4PROP_T prop; + void *next; +} SMB_ACE4_INT_T; + +#define SMB_ACL4_INT_MAGIC 0x29A3E792 +typedef struct _SMB_ACL4_INT_T +{ + uint32 magic; + uint32 naces; + SMB_ACE4_INT_T *first; + SMB_ACE4_INT_T *last; +} SMB_ACL4_INT_T; + +extern struct current_user current_user; +extern int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid); +extern BOOL unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, + uint32 security_info_sent, SEC_DESC *psd); + +static SMB_ACL4_INT_T *get_validated_aclint(SMB4ACL_T *acl) +{ + SMB_ACL4_INT_T *aclint = (SMB_ACL4_INT_T *)acl; + if (acl==NULL) + { + DEBUG(2, ("acl is NULL\n")); + errno = EINVAL; + return NULL; + } + if (aclint->magic!=SMB_ACL4_INT_MAGIC) + { + DEBUG(2, ("aclint bad magic 0x%x\n", aclint->magic)); + errno = EINVAL; + return NULL; + } + return aclint; +} + +static SMB_ACE4_INT_T *get_validated_aceint(SMB4ACE_T *ace) +{ + SMB_ACE4_INT_T *aceint = (SMB_ACE4_INT_T *)ace; + if (ace==NULL) + { + DEBUG(2, ("ace is NULL\n")); + errno = EINVAL; + return NULL; + } + if (aceint->magic!=SMB_ACE4_INT_MAGIC) + { + DEBUG(2, ("aceint bad magic 0x%x\n", aceint->magic)); + errno = EINVAL; + return NULL; + } + return aceint; +} + +SMB4ACL_T *smb_create_smb4acl(void) +{ + TALLOC_CTX *mem_ctx = main_loop_talloc_get(); + SMB_ACL4_INT_T *acl = (SMB_ACL4_INT_T *)talloc_size(mem_ctx, sizeof(SMB_ACL4_INT_T)); + if (acl==NULL) + { + DEBUG(0, ("talloc_size failed\n")); + errno = ENOMEM; + return NULL; + } + memset(acl, 0, sizeof(SMB_ACL4_INT_T)); + acl->magic = SMB_ACL4_INT_MAGIC; + /* acl->first, last = NULL not needed */ + return (SMB4ACL_T *)acl; +} + +SMB4ACE_T *smb_add_ace4(SMB4ACL_T *acl, SMB_ACE4PROP_T *prop) +{ + SMB_ACL4_INT_T *aclint = get_validated_aclint(acl); + TALLOC_CTX *mem_ctx = main_loop_talloc_get(); + SMB_ACE4_INT_T *ace; + + ace = (SMB_ACE4_INT_T *)talloc_size(mem_ctx, sizeof(SMB_ACE4_INT_T)); + if (ace==NULL) + { + DEBUG(0, ("talloc_size failed\n")); + errno = ENOMEM; + return NULL; + } + memset(ace, 0, sizeof(SMB_ACE4_INT_T)); + ace->magic = SMB_ACE4_INT_MAGIC; + /* ace->next = NULL not needed */ + memcpy(&ace->prop, prop, sizeof(SMB_ACE4PROP_T)); + + if (aclint->first==NULL) + { + aclint->first = ace; + aclint->last = ace; + } else { + aclint->last->next = (void *)ace; + aclint->last = ace; + } + aclint->naces++; + + return (SMB4ACE_T *)ace; +} + +SMB_ACE4PROP_T *smb_get_ace4(SMB4ACE_T *ace) +{ + SMB_ACE4_INT_T *aceint = get_validated_aceint(ace); + if (aceint==NULL) + return NULL; + + return &aceint->prop; +} + +SMB4ACE_T *smb_next_ace4(SMB4ACE_T *ace) +{ + SMB_ACE4_INT_T *aceint = get_validated_aceint(ace); + if (aceint==NULL) + return NULL; + + return (SMB4ACE_T *)aceint->next; +} + +SMB4ACE_T *smb_first_ace4(SMB4ACL_T *acl) +{ + SMB_ACL4_INT_T *aclint = get_validated_aclint(acl); + if (aclint==NULL) + return NULL; + + return (SMB4ACE_T *)aclint->first; +} + +uint32 smb_get_naces(SMB4ACL_T *acl) +{ + SMB_ACL4_INT_T *aclint = get_validated_aclint(acl); + if (aclint==NULL) + return 0; + + return aclint->naces; +} + +static int smbacl4_GetFileOwner(files_struct *fsp, SMB_STRUCT_STAT *psbuf) +{ + memset(psbuf, 0, sizeof(SMB_STRUCT_STAT)); + if (fsp->is_directory || fsp->fh->fd == -1) { + /* Get the stat struct for the owner info. */ + if (SMB_VFS_STAT(fsp->conn,fsp->fsp_name, psbuf) != 0) + { + DEBUG(8, ("SMB_VFS_STAT failed with error %s\n", + strerror(errno))); + return -1; + } + } else { + if (SMB_VFS_FSTAT(fsp,fsp->fh->fd, psbuf) != 0) + { + DEBUG(8, ("SMB_VFS_FSTAT failed with error %s\n", + strerror(errno))); + return -1; + } + } + + return 0; +} + +static BOOL smbacl4_nfs42win(SMB4ACL_T *acl, /* in */ + DOM_SID *psid_owner, /* in */ + DOM_SID *psid_group, /* in */ + SEC_ACE **ppnt_ace_list, /* out */ + int *pgood_aces /* out */ +) +{ + SMB_ACL4_INT_T *aclint = (SMB_ACL4_INT_T *)acl; + SMB_ACE4_INT_T *aceint; + SEC_ACE *nt_ace_list = NULL; + int good_aces = 0; + TALLOC_CTX *mem_ctx = main_loop_talloc_get(); + + DEBUG(10, ("smbacl_nfs42win entered")); + + aclint = get_validated_aclint(acl); + if (aclint==NULL) + return False; + + nt_ace_list = (SEC_ACE *)talloc_size(mem_ctx, aclint->naces * sizeof(SEC_ACE)); + if (nt_ace_list==NULL) + { + DEBUG(10, ("talloc error")); + errno = ENOMEM; + return False; + } + memset(nt_ace_list, 0, aclint->naces * sizeof(SEC_ACE)); + + for (aceint=aclint->first; aceint!=NULL; aceint=(SMB_ACE4_INT_T *)aceint->next) { + SEC_ACCESS mask; + DOM_SID sid; + SMB_ACE4PROP_T *ace = &aceint->prop; + + DEBUG(10, ("magic: 0x%x, type: %d, iflags: %x, flags: %x, mask: %x, " + "who: %d\n", aceint->magic, ace->aceType, ace->flags, + ace->aceFlags, ace->aceMask, ace->who.id)); + + SMB_ASSERT(aceint->magic==SMB_ACE4_INT_MAGIC); + + if (ace->flags & SMB_ACE4_ID_SPECIAL) { + switch (ace->who.special_id) { + case SMB_ACE4_WHO_OWNER: + sid_copy(&sid, psid_owner); + break; + case SMB_ACE4_WHO_GROUP: + sid_copy(&sid, psid_group); + break; + case SMB_ACE4_WHO_EVERYONE: + sid_copy(&sid, &global_sid_World); + break; + default: + DEBUG(8, ("invalid special who id %d " + "ignored\n", ace->who.special_id)); + } + } else { + if (ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) { + gid_to_sid(&sid, ace->who.gid); + } else { + uid_to_sid(&sid, ace->who.uid); + } + } + DEBUG(10, ("mapped %d to %s\n", ace->who.id, + sid_string_static(&sid))); + + init_sec_access(&mask, ace->aceMask); + init_sec_ace(&nt_ace_list[good_aces++], &sid, + ace->aceType, mask, + ace->aceFlags & 0xf); + } + + *ppnt_ace_list = nt_ace_list; + *pgood_aces = good_aces; + + return True; +} + +size_t smb_get_nt_acl_nfs4(files_struct *fsp, + uint32 security_info, + SEC_DESC **ppdesc, SMB4ACL_T *acl) +{ + int good_aces = 0; + SMB_STRUCT_STAT sbuf; + DOM_SID sid_owner, sid_group; + size_t sd_size = 0; + SEC_ACE *nt_ace_list = NULL; + SEC_ACL *psa = NULL; + TALLOC_CTX *mem_ctx = main_loop_talloc_get(); + + DEBUG(10, ("smb_get_nt_acl_nfs4 invoked for %s\n", fsp->fsp_name)); + + if (acl==NULL || smb_get_naces(acl)==0) + return 0; /* special because we shouldn't alloc 0 for win */ + + if (smbacl4_GetFileOwner(fsp, &sbuf)) + return 0; + + uid_to_sid(&sid_owner, sbuf.st_uid); + gid_to_sid(&sid_group, sbuf.st_gid); + + if (smbacl4_nfs42win(acl, + &sid_owner, + &sid_group, + &nt_ace_list, + &good_aces + )==False) { + DEBUG(8,("smbacl4_nfs42win failed\n")); + return 0; + } + + psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, + good_aces, nt_ace_list); + if (psa == NULL) { + DEBUG(2,("make_sec_acl failed\n")); + return 0; + } + + DEBUG(10,("after make sec_acl\n")); + *ppdesc = make_sec_desc(mem_ctx, SEC_DESC_REVISION, + SEC_DESC_SELF_RELATIVE, + (security_info & OWNER_SECURITY_INFORMATION) + ? &sid_owner : NULL, + (security_info & GROUP_SECURITY_INFORMATION) + ? &sid_group : NULL, + NULL, psa, &sd_size); + if (*ppdesc==NULL) { + DEBUG(2,("make_sec_desc failed\n")); + return 0; + } + + DEBUG(10, ("smb_get_nt_acl_nfs4 successfully exited with sd_size %d\n", sd_size)); + return sd_size; +} + +enum smbacl4_mode_enum {e_simple=0, e_special=1}; +enum smbacl4_acedup_enum {e_dontcare=0, e_reject=1, e_ignore=2, e_merge=3}; + +typedef struct _smbacl4_vfs_params { + enum smbacl4_mode_enum mode; + BOOL do_chown; + enum smbacl4_acedup_enum acedup; +} smbacl4_vfs_params; + +/* + * Gather special parameters for NFS4 ACL handling + */ +static int smbacl4_get_vfs_params( + const char *type_name, + files_struct *fsp, + smbacl4_vfs_params *params +) +{ + static const struct enum_list enum_smbacl4_modes[] = { + { e_simple, "simple" }, + { e_special, "special" } + }; + static const struct enum_list enum_smbacl4_acedups[] = { + { e_dontcare, "dontcare" }, + { e_reject, "reject" }, + { e_ignore, "ignore" }, + { e_merge, "merge" }, + }; + + memset(params, 0, sizeof(smbacl4_vfs_params)); + params->mode = (enum smbacl4_mode_enum)lp_parm_enum( + SNUM(fsp->conn), type_name, + "mode", enum_smbacl4_modes, e_simple); + params->do_chown = lp_parm_bool(SNUM(fsp->conn), type_name, + "chown", True); + params->acedup = (enum smbacl4_acedup_enum)lp_parm_enum( + SNUM(fsp->conn), type_name, + "acedup", enum_smbacl4_acedups, e_dontcare); + + DEBUG(10, ("mode:%s, do_chown:%s, acedup: %s\n", + enum_smbacl4_modes[params->mode].name, + params->do_chown ? "true" : "false", + enum_smbacl4_acedups[params->acedup].name)); + + return 0; +} + +static void smbacl4_dump_nfs4acl(int level, SMB4ACL_T *acl) +{ + SMB_ACL4_INT_T *aclint = get_validated_aclint(acl); + SMB_ACE4_INT_T *aceint; + + DEBUG(level, ("NFS4ACL: size=%d\n", aclint->naces)); + + for(aceint = aclint->first; aceint!=NULL; aceint=(SMB_ACE4_INT_T *)aceint->next) { + SMB_ACE4PROP_T *ace = &aceint->prop; + + DEBUG(level, ("\tACE: type=%d, flags=0x%x, fflags=0x%x, mask=0x%x, id=%d\n", + ace->aceType, + ace->aceFlags, ace->flags, + ace->aceMask, + ace->who.id)); + } +} + +/* + * Find 2 NFS4 who-special ACE property (non-copy!!!) + * match nonzero if "special" and who is equal + * return ace if found matching; otherwise NULL + */ +static SMB_ACE4PROP_T *smbacl4_find_equal_special( + SMB4ACL_T *acl, + SMB_ACE4PROP_T *aceNew) +{ + SMB_ACL4_INT_T *aclint = get_validated_aclint(acl); + SMB_ACE4_INT_T *aceint; + + for(aceint = aclint->first; aceint!=NULL; aceint=(SMB_ACE4_INT_T *)aceint->next) { + SMB_ACE4PROP_T *ace = &aceint->prop; + + if (ace->flags == aceNew->flags && + ace->aceType==aceNew->aceType && + (ace->aceFlags&SMB_ACE4_IDENTIFIER_GROUP)== + (aceNew->aceFlags&SMB_ACE4_IDENTIFIER_GROUP) + ) { + /* keep type safety; e.g. gid is an u.short */ + if (ace->flags & SMB_ACE4_ID_SPECIAL) + { + if (ace->who.special_id==aceNew->who.special_id) + return ace; + } else { + if (ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) + { + if (ace->who.gid==aceNew->who.gid) + return ace; + } else { + if (ace->who.uid==aceNew->who.uid) + return ace; + } + } + } + } + + return NULL; +} + +static int smbacl4_fill_ace4( + TALLOC_CTX *mem_ctx, + smbacl4_vfs_params *params, + uid_t ownerUID, + gid_t ownerGID, + SEC_ACE *ace_nt, /* input */ + SMB_ACE4PROP_T *ace_v4 /* output */ +) +{ + const char *dom, *name; + enum SID_NAME_USE type; + uid_t uid; + gid_t gid; + + DEBUG(10, ("got ace for %s\n", + sid_string_static(&ace_nt->trustee))); + + memset(ace_v4, 0, sizeof(SMB_ACE4PROP_T)); + ace_v4->aceType = ace_nt->type; /* only ACCES|DENY supported right now */ + ace_v4->aceFlags = ace_nt->flags & SEC_ACE_FLAG_VALID_INHERIT; + ace_v4->aceMask = ace_nt->info.mask & + (STD_RIGHT_ALL_ACCESS | SA_RIGHT_FILE_ALL_ACCESS); + + if (ace_v4->aceFlags!=ace_nt->flags) + DEBUG(9, ("ace_v4->aceFlags(0x%x)!=ace_nt->flags(0x%x)\n", + ace_v4->aceFlags, ace_nt->flags)); + + if (ace_v4->aceMask!=ace_nt->info.mask) + DEBUG(9, ("ace_v4->aceMask(0x%x)!=ace_nt->info.mask(0x%x)\n", + ace_v4->aceMask, ace_nt->info.mask)); + + if (sid_equal(&ace_nt->trustee, &global_sid_World)) { + ace_v4->who.special_id = SMB_ACE4_WHO_EVERYONE; + ace_v4->flags |= SMB_ACE4_ID_SPECIAL; + } else { + if (!lookup_sid(mem_ctx, &ace_nt->trustee, &dom, &name, &type)) { + DEBUG(8, ("Could not find %s' type\n", + sid_string_static(&ace_nt->trustee))); + errno = EINVAL; + return -1; + } + + if (type == SID_NAME_USER) { + if (!sid_to_uid(&ace_nt->trustee, &uid)) { + DEBUG(2, ("Could not convert %s to uid\n", + sid_string_static(&ace_nt->trustee))); + return -1; + } + + if (params->mode==e_special && uid==ownerUID) { + ace_v4->flags |= SMB_ACE4_ID_SPECIAL; + ace_v4->who.special_id = SMB_ACE4_WHO_OWNER; + } else { + ace_v4->who.uid = uid; + } + } else { /* else group? - TODO check it... */ + if (!sid_to_gid(&ace_nt->trustee, &gid)) { + DEBUG(2, ("Could not convert %s to gid\n", + sid_string_static(&ace_nt->trustee))); + return -1; + } + ace_v4->aceFlags |= SMB_ACE4_IDENTIFIER_GROUP; + + if (params->mode==e_special && gid==ownerGID) { + ace_v4->flags |= SMB_ACE4_ID_SPECIAL; + ace_v4->who.special_id = SMB_ACE4_WHO_GROUP; + } else { + ace_v4->who.gid = gid; + } + } + } + + return 0; /* OK */ +} + +static int smbacl4_MergeIgnoreReject( + enum smbacl4_acedup_enum acedup, + SMB4ACL_T *acl, /* may modify it */ + SMB_ACE4PROP_T *ace, /* the "new" ACE */ + BOOL *paddNewACE, + int i +) +{ + int result = 0; + SMB_ACE4PROP_T *ace4found = smbacl4_find_equal_special(acl, ace); + if (ace4found) + { + switch(acedup) + { + case e_merge: /* "merge" flags */ + *paddNewACE = False; + ace4found->aceFlags |= ace->aceFlags; + ace4found->aceMask |= ace->aceMask; + break; + case e_ignore: /* leave out this record */ + *paddNewACE = False; + break; + case e_reject: /* do an error */ + DEBUG(8, ("ACL rejected by duplicate nt ace#%d\n", i)); + errno = EINVAL; /* SHOULD be set on any _real_ error */ + result = -1; + break; + default: + break; + } + } + return result; +} + +static SMB4ACL_T *smbacl4_win2nfs4( + SEC_ACL *dacl, + smbacl4_vfs_params *pparams, + uid_t ownerUID, + gid_t ownerGID +) +{ + SMB4ACL_T *acl; + uint32 i; + TALLOC_CTX *mem_ctx = main_loop_talloc_get(); + + DEBUG(10, ("smbacl4_win2nfs4 invoked\n")); + + acl = smb_create_smb4acl(); + if (acl==NULL) + return NULL; + + for(i=0; inum_aces; i++) { + SMB_ACE4PROP_T ace_v4; + BOOL addNewACE = True; + + if (smbacl4_fill_ace4(mem_ctx, pparams, ownerUID, ownerGID, + dacl->ace + i, &ace_v4)) + return NULL; + + if (pparams->acedup!=e_dontcare) { + if (smbacl4_MergeIgnoreReject(pparams->acedup, acl, + &ace_v4, &addNewACE, i)) + return NULL; + } + + if (addNewACE) + smb_add_ace4(acl, &ace_v4); + } + + return acl; +} + +BOOL smb_set_nt_acl_nfs4(files_struct *fsp, + uint32 security_info_sent, + SEC_DESC *psd, + set_nfs4acl_native_fn_t set_nfs4_native) +{ + smbacl4_vfs_params params; + SMB4ACL_T *acl = NULL; + BOOL result; + + SMB_STRUCT_STAT sbuf; + BOOL need_chown = False; + uid_t newUID = (uid_t)-1; + gid_t newGID = (gid_t)-1; + + DEBUG(10, ("smb_set_nt_acl_nfs4 invoked for %s\n", fsp->fsp_name)); + + if ((security_info_sent & (DACL_SECURITY_INFORMATION | + GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION)) == 0) + { + DEBUG(9, ("security_info_sent (0x%x) ignored\n", + security_info_sent)); + return True; /* won't show error - later to be refined... */ + } + + /* Special behaviours */ + if (smbacl4_get_vfs_params(SMBACL4_PARAM_TYPE_NAME, fsp, ¶ms)) + return False; + + if (smbacl4_GetFileOwner(fsp, &sbuf)) + return False; + + /* chown logic is a copy/paste from posix_acl.c:set_nt_acl */ + if (!unpack_nt_owners(SNUM(fsp->conn), &newUID, &newGID, security_info_sent, psd)) + { + DEBUG(8, ("unpack_nt_owners failed")); + return False; + } + if (((newUID != (uid_t)-1) && (sbuf.st_uid != newUID)) || + ((newGID != (gid_t)-1) && (sbuf.st_gid != newGID))) { + need_chown = True; + } + if (need_chown) { + if ((newUID == (uid_t)-1 || newUID == current_user.ut.uid)) { + if(try_chown(fsp->conn, fsp->fsp_name, newUID, newGID)) { + DEBUG(3,("chown %s, %u, %u failed. Error = %s.\n", + fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID, strerror(errno) )); + return False; + } + DEBUG(10,("chown %s, %u, %u succeeded.\n", + fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID)); + if (smbacl4_GetFileOwner(fsp, &sbuf)) + return False; + need_chown = False; + } else { /* chown is needed, but _after_ changing acl */ + sbuf.st_uid = newUID; /* OWNER@ in case of e_special */ + sbuf.st_gid = newGID; /* GROUP@ in case of e_special */ + } + } + + if ((security_info_sent & DACL_SECURITY_INFORMATION)!=0 && psd->dacl!=NULL) + { + acl = smbacl4_win2nfs4(psd->dacl, ¶ms, sbuf.st_uid, sbuf.st_gid); + if (!acl) + return False; + + smbacl4_dump_nfs4acl(10, acl); + + result = set_nfs4_native(fsp, acl); + if (result!=True) + { + DEBUG(10, ("set_nfs4_native failed with %s\n", strerror(errno))); + return False; + } + } else + DEBUG(10, ("no dacl found; security_info_sent = 0x%x\n", security_info_sent)); + + /* Any chown pending? */ + if (need_chown) { + DEBUG(3,("chown#2 %s. uid = %u, gid = %u.\n", + fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID)); + if (try_chown(fsp->conn, fsp->fsp_name, newUID, newGID)) { + DEBUG(2,("chown#2 %s, %u, %u failed. Error = %s.\n", + fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID, + strerror(errno))); + return False; + } + DEBUG(10,("chown#2 %s, %u, %u succeeded.\n", + fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID)); + } + + DEBUG(10, ("smb_set_nt_acl_nfs4 succeeded\n")); + return True; -- cgit From d42a96b3ec3dec1e2aa958813ae56326e7b02789 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 1 Aug 2006 18:40:19 +0000 Subject: r17367: Reverting the ab code. Note I'm not saying this code is wrong or bad or anything, just that it needs to be discussed & reviewed on the samba-technical list before we add a platform-specific NFSv4 mapping. That way lies a lot of future pain :-). Jeremy. (This used to be commit 330899ec30ffceb798e3a8362d20e103e20b2897) --- source3/modules/nfs4_acls.c | 668 -------------------------------------------- 1 file changed, 668 deletions(-) delete mode 100644 source3/modules/nfs4_acls.c (limited to 'source3/modules/nfs4_acls.c') diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c deleted file mode 100644 index 795afee45a..0000000000 --- a/source3/modules/nfs4_acls.c +++ /dev/null @@ -1,668 +0,0 @@ -/* - * NFS4 ACL handling - * - * Copyright (C) Jim McDonough, 2006 - * Major code contributions from Peter Somogyi, somogyi@de.ibm.com - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "includes.h" -#include "nfs4_acls.h" - -#define SMBACL4_PARAM_TYPE_NAME "nfs4" - -#define SMB_ACE4_INT_MAGIC 0x76F8A967 -typedef struct _SMB_ACE4_INT_T -{ - uint32 magic; - SMB_ACE4PROP_T prop; - void *next; -} SMB_ACE4_INT_T; - -#define SMB_ACL4_INT_MAGIC 0x29A3E792 -typedef struct _SMB_ACL4_INT_T -{ - uint32 magic; - uint32 naces; - SMB_ACE4_INT_T *first; - SMB_ACE4_INT_T *last; -} SMB_ACL4_INT_T; - -extern struct current_user current_user; -extern int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid); -extern BOOL unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, - uint32 security_info_sent, SEC_DESC *psd); - -static SMB_ACL4_INT_T *get_validated_aclint(SMB4ACL_T *acl) -{ - SMB_ACL4_INT_T *aclint = (SMB_ACL4_INT_T *)acl; - if (acl==NULL) - { - DEBUG(2, ("acl is NULL\n")); - errno = EINVAL; - return NULL; - } - if (aclint->magic!=SMB_ACL4_INT_MAGIC) - { - DEBUG(2, ("aclint bad magic 0x%x\n", aclint->magic)); - errno = EINVAL; - return NULL; - } - return aclint; -} - -static SMB_ACE4_INT_T *get_validated_aceint(SMB4ACE_T *ace) -{ - SMB_ACE4_INT_T *aceint = (SMB_ACE4_INT_T *)ace; - if (ace==NULL) - { - DEBUG(2, ("ace is NULL\n")); - errno = EINVAL; - return NULL; - } - if (aceint->magic!=SMB_ACE4_INT_MAGIC) - { - DEBUG(2, ("aceint bad magic 0x%x\n", aceint->magic)); - errno = EINVAL; - return NULL; - } - return aceint; -} - -SMB4ACL_T *smb_create_smb4acl(void) -{ - TALLOC_CTX *mem_ctx = main_loop_talloc_get(); - SMB_ACL4_INT_T *acl = (SMB_ACL4_INT_T *)talloc_size(mem_ctx, sizeof(SMB_ACL4_INT_T)); - if (acl==NULL) - { - DEBUG(0, ("talloc_size failed\n")); - errno = ENOMEM; - return NULL; - } - memset(acl, 0, sizeof(SMB_ACL4_INT_T)); - acl->magic = SMB_ACL4_INT_MAGIC; - /* acl->first, last = NULL not needed */ - return (SMB4ACL_T *)acl; -} - -SMB4ACE_T *smb_add_ace4(SMB4ACL_T *acl, SMB_ACE4PROP_T *prop) -{ - SMB_ACL4_INT_T *aclint = get_validated_aclint(acl); - TALLOC_CTX *mem_ctx = main_loop_talloc_get(); - SMB_ACE4_INT_T *ace; - - ace = (SMB_ACE4_INT_T *)talloc_size(mem_ctx, sizeof(SMB_ACE4_INT_T)); - if (ace==NULL) - { - DEBUG(0, ("talloc_size failed\n")); - errno = ENOMEM; - return NULL; - } - memset(ace, 0, sizeof(SMB_ACE4_INT_T)); - ace->magic = SMB_ACE4_INT_MAGIC; - /* ace->next = NULL not needed */ - memcpy(&ace->prop, prop, sizeof(SMB_ACE4PROP_T)); - - if (aclint->first==NULL) - { - aclint->first = ace; - aclint->last = ace; - } else { - aclint->last->next = (void *)ace; - aclint->last = ace; - } - aclint->naces++; - - return (SMB4ACE_T *)ace; -} - -SMB_ACE4PROP_T *smb_get_ace4(SMB4ACE_T *ace) -{ - SMB_ACE4_INT_T *aceint = get_validated_aceint(ace); - if (aceint==NULL) - return NULL; - - return &aceint->prop; -} - -SMB4ACE_T *smb_next_ace4(SMB4ACE_T *ace) -{ - SMB_ACE4_INT_T *aceint = get_validated_aceint(ace); - if (aceint==NULL) - return NULL; - - return (SMB4ACE_T *)aceint->next; -} - -SMB4ACE_T *smb_first_ace4(SMB4ACL_T *acl) -{ - SMB_ACL4_INT_T *aclint = get_validated_aclint(acl); - if (aclint==NULL) - return NULL; - - return (SMB4ACE_T *)aclint->first; -} - -uint32 smb_get_naces(SMB4ACL_T *acl) -{ - SMB_ACL4_INT_T *aclint = get_validated_aclint(acl); - if (aclint==NULL) - return 0; - - return aclint->naces; -} - -static int smbacl4_GetFileOwner(files_struct *fsp, SMB_STRUCT_STAT *psbuf) -{ - memset(psbuf, 0, sizeof(SMB_STRUCT_STAT)); - if (fsp->is_directory || fsp->fh->fd == -1) { - /* Get the stat struct for the owner info. */ - if (SMB_VFS_STAT(fsp->conn,fsp->fsp_name, psbuf) != 0) - { - DEBUG(8, ("SMB_VFS_STAT failed with error %s\n", - strerror(errno))); - return -1; - } - } else { - if (SMB_VFS_FSTAT(fsp,fsp->fh->fd, psbuf) != 0) - { - DEBUG(8, ("SMB_VFS_FSTAT failed with error %s\n", - strerror(errno))); - return -1; - } - } - - return 0; -} - -static BOOL smbacl4_nfs42win(SMB4ACL_T *acl, /* in */ - DOM_SID *psid_owner, /* in */ - DOM_SID *psid_group, /* in */ - SEC_ACE **ppnt_ace_list, /* out */ - int *pgood_aces /* out */ -) -{ - SMB_ACL4_INT_T *aclint = (SMB_ACL4_INT_T *)acl; - SMB_ACE4_INT_T *aceint; - SEC_ACE *nt_ace_list = NULL; - int good_aces = 0; - TALLOC_CTX *mem_ctx = main_loop_talloc_get(); - - DEBUG(10, ("smbacl_nfs42win entered")); - - aclint = get_validated_aclint(acl); - if (aclint==NULL) - return False; - - nt_ace_list = (SEC_ACE *)talloc_size(mem_ctx, aclint->naces * sizeof(SEC_ACE)); - if (nt_ace_list==NULL) - { - DEBUG(10, ("talloc error")); - errno = ENOMEM; - return False; - } - memset(nt_ace_list, 0, aclint->naces * sizeof(SEC_ACE)); - - for (aceint=aclint->first; aceint!=NULL; aceint=(SMB_ACE4_INT_T *)aceint->next) { - SEC_ACCESS mask; - DOM_SID sid; - SMB_ACE4PROP_T *ace = &aceint->prop; - - DEBUG(10, ("magic: 0x%x, type: %d, iflags: %x, flags: %x, mask: %x, " - "who: %d\n", aceint->magic, ace->aceType, ace->flags, - ace->aceFlags, ace->aceMask, ace->who.id)); - - SMB_ASSERT(aceint->magic==SMB_ACE4_INT_MAGIC); - - if (ace->flags & SMB_ACE4_ID_SPECIAL) { - switch (ace->who.special_id) { - case SMB_ACE4_WHO_OWNER: - sid_copy(&sid, psid_owner); - break; - case SMB_ACE4_WHO_GROUP: - sid_copy(&sid, psid_group); - break; - case SMB_ACE4_WHO_EVERYONE: - sid_copy(&sid, &global_sid_World); - break; - default: - DEBUG(8, ("invalid special who id %d " - "ignored\n", ace->who.special_id)); - } - } else { - if (ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) { - gid_to_sid(&sid, ace->who.gid); - } else { - uid_to_sid(&sid, ace->who.uid); - } - } - DEBUG(10, ("mapped %d to %s\n", ace->who.id, - sid_string_static(&sid))); - - init_sec_access(&mask, ace->aceMask); - init_sec_ace(&nt_ace_list[good_aces++], &sid, - ace->aceType, mask, - ace->aceFlags & 0xf); - } - - *ppnt_ace_list = nt_ace_list; - *pgood_aces = good_aces; - - return True; -} - -size_t smb_get_nt_acl_nfs4(files_struct *fsp, - uint32 security_info, - SEC_DESC **ppdesc, SMB4ACL_T *acl) -{ - int good_aces = 0; - SMB_STRUCT_STAT sbuf; - DOM_SID sid_owner, sid_group; - size_t sd_size = 0; - SEC_ACE *nt_ace_list = NULL; - SEC_ACL *psa = NULL; - TALLOC_CTX *mem_ctx = main_loop_talloc_get(); - - DEBUG(10, ("smb_get_nt_acl_nfs4 invoked for %s\n", fsp->fsp_name)); - - if (acl==NULL || smb_get_naces(acl)==0) - return 0; /* special because we shouldn't alloc 0 for win */ - - if (smbacl4_GetFileOwner(fsp, &sbuf)) - return 0; - - uid_to_sid(&sid_owner, sbuf.st_uid); - gid_to_sid(&sid_group, sbuf.st_gid); - - if (smbacl4_nfs42win(acl, - &sid_owner, - &sid_group, - &nt_ace_list, - &good_aces - )==False) { - DEBUG(8,("smbacl4_nfs42win failed\n")); - return 0; - } - - psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, - good_aces, nt_ace_list); - if (psa == NULL) { - DEBUG(2,("make_sec_acl failed\n")); - return 0; - } - - DEBUG(10,("after make sec_acl\n")); - *ppdesc = make_sec_desc(mem_ctx, SEC_DESC_REVISION, - SEC_DESC_SELF_RELATIVE, - (security_info & OWNER_SECURITY_INFORMATION) - ? &sid_owner : NULL, - (security_info & GROUP_SECURITY_INFORMATION) - ? &sid_group : NULL, - NULL, psa, &sd_size); - if (*ppdesc==NULL) { - DEBUG(2,("make_sec_desc failed\n")); - return 0; - } - - DEBUG(10, ("smb_get_nt_acl_nfs4 successfully exited with sd_size %d\n", sd_size)); - return sd_size; -} - -enum smbacl4_mode_enum {e_simple=0, e_special=1}; -enum smbacl4_acedup_enum {e_dontcare=0, e_reject=1, e_ignore=2, e_merge=3}; - -typedef struct _smbacl4_vfs_params { - enum smbacl4_mode_enum mode; - BOOL do_chown; - enum smbacl4_acedup_enum acedup; -} smbacl4_vfs_params; - -/* - * Gather special parameters for NFS4 ACL handling - */ -static int smbacl4_get_vfs_params( - const char *type_name, - files_struct *fsp, - smbacl4_vfs_params *params -) -{ - static const struct enum_list enum_smbacl4_modes[] = { - { e_simple, "simple" }, - { e_special, "special" } - }; - static const struct enum_list enum_smbacl4_acedups[] = { - { e_dontcare, "dontcare" }, - { e_reject, "reject" }, - { e_ignore, "ignore" }, - { e_merge, "merge" }, - }; - - memset(params, 0, sizeof(smbacl4_vfs_params)); - params->mode = (enum smbacl4_mode_enum)lp_parm_enum( - SNUM(fsp->conn), type_name, - "mode", enum_smbacl4_modes, e_simple); - params->do_chown = lp_parm_bool(SNUM(fsp->conn), type_name, - "chown", True); - params->acedup = (enum smbacl4_acedup_enum)lp_parm_enum( - SNUM(fsp->conn), type_name, - "acedup", enum_smbacl4_acedups, e_dontcare); - - DEBUG(10, ("mode:%s, do_chown:%s, acedup: %s\n", - enum_smbacl4_modes[params->mode].name, - params->do_chown ? "true" : "false", - enum_smbacl4_acedups[params->acedup].name)); - - return 0; -} - -static void smbacl4_dump_nfs4acl(int level, SMB4ACL_T *acl) -{ - SMB_ACL4_INT_T *aclint = get_validated_aclint(acl); - SMB_ACE4_INT_T *aceint; - - DEBUG(level, ("NFS4ACL: size=%d\n", aclint->naces)); - - for(aceint = aclint->first; aceint!=NULL; aceint=(SMB_ACE4_INT_T *)aceint->next) { - SMB_ACE4PROP_T *ace = &aceint->prop; - - DEBUG(level, ("\tACE: type=%d, flags=0x%x, fflags=0x%x, mask=0x%x, id=%d\n", - ace->aceType, - ace->aceFlags, ace->flags, - ace->aceMask, - ace->who.id)); - } -} - -/* - * Find 2 NFS4 who-special ACE property (non-copy!!!) - * match nonzero if "special" and who is equal - * return ace if found matching; otherwise NULL - */ -static SMB_ACE4PROP_T *smbacl4_find_equal_special( - SMB4ACL_T *acl, - SMB_ACE4PROP_T *aceNew) -{ - SMB_ACL4_INT_T *aclint = get_validated_aclint(acl); - SMB_ACE4_INT_T *aceint; - - for(aceint = aclint->first; aceint!=NULL; aceint=(SMB_ACE4_INT_T *)aceint->next) { - SMB_ACE4PROP_T *ace = &aceint->prop; - - if (ace->flags == aceNew->flags && - ace->aceType==aceNew->aceType && - (ace->aceFlags&SMB_ACE4_IDENTIFIER_GROUP)== - (aceNew->aceFlags&SMB_ACE4_IDENTIFIER_GROUP) - ) { - /* keep type safety; e.g. gid is an u.short */ - if (ace->flags & SMB_ACE4_ID_SPECIAL) - { - if (ace->who.special_id==aceNew->who.special_id) - return ace; - } else { - if (ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) - { - if (ace->who.gid==aceNew->who.gid) - return ace; - } else { - if (ace->who.uid==aceNew->who.uid) - return ace; - } - } - } - } - - return NULL; -} - -static int smbacl4_fill_ace4( - TALLOC_CTX *mem_ctx, - smbacl4_vfs_params *params, - uid_t ownerUID, - gid_t ownerGID, - SEC_ACE *ace_nt, /* input */ - SMB_ACE4PROP_T *ace_v4 /* output */ -) -{ - const char *dom, *name; - enum SID_NAME_USE type; - uid_t uid; - gid_t gid; - - DEBUG(10, ("got ace for %s\n", - sid_string_static(&ace_nt->trustee))); - - memset(ace_v4, 0, sizeof(SMB_ACE4PROP_T)); - ace_v4->aceType = ace_nt->type; /* only ACCES|DENY supported right now */ - ace_v4->aceFlags = ace_nt->flags & SEC_ACE_FLAG_VALID_INHERIT; - ace_v4->aceMask = ace_nt->info.mask & - (STD_RIGHT_ALL_ACCESS | SA_RIGHT_FILE_ALL_ACCESS); - - if (ace_v4->aceFlags!=ace_nt->flags) - DEBUG(9, ("ace_v4->aceFlags(0x%x)!=ace_nt->flags(0x%x)\n", - ace_v4->aceFlags, ace_nt->flags)); - - if (ace_v4->aceMask!=ace_nt->info.mask) - DEBUG(9, ("ace_v4->aceMask(0x%x)!=ace_nt->info.mask(0x%x)\n", - ace_v4->aceMask, ace_nt->info.mask)); - - if (sid_equal(&ace_nt->trustee, &global_sid_World)) { - ace_v4->who.special_id = SMB_ACE4_WHO_EVERYONE; - ace_v4->flags |= SMB_ACE4_ID_SPECIAL; - } else { - if (!lookup_sid(mem_ctx, &ace_nt->trustee, &dom, &name, &type)) { - DEBUG(8, ("Could not find %s' type\n", - sid_string_static(&ace_nt->trustee))); - errno = EINVAL; - return -1; - } - - if (type == SID_NAME_USER) { - if (!sid_to_uid(&ace_nt->trustee, &uid)) { - DEBUG(2, ("Could not convert %s to uid\n", - sid_string_static(&ace_nt->trustee))); - return -1; - } - - if (params->mode==e_special && uid==ownerUID) { - ace_v4->flags |= SMB_ACE4_ID_SPECIAL; - ace_v4->who.special_id = SMB_ACE4_WHO_OWNER; - } else { - ace_v4->who.uid = uid; - } - } else { /* else group? - TODO check it... */ - if (!sid_to_gid(&ace_nt->trustee, &gid)) { - DEBUG(2, ("Could not convert %s to gid\n", - sid_string_static(&ace_nt->trustee))); - return -1; - } - ace_v4->aceFlags |= SMB_ACE4_IDENTIFIER_GROUP; - - if (params->mode==e_special && gid==ownerGID) { - ace_v4->flags |= SMB_ACE4_ID_SPECIAL; - ace_v4->who.special_id = SMB_ACE4_WHO_GROUP; - } else { - ace_v4->who.gid = gid; - } - } - } - - return 0; /* OK */ -} - -static int smbacl4_MergeIgnoreReject( - enum smbacl4_acedup_enum acedup, - SMB4ACL_T *acl, /* may modify it */ - SMB_ACE4PROP_T *ace, /* the "new" ACE */ - BOOL *paddNewACE, - int i -) -{ - int result = 0; - SMB_ACE4PROP_T *ace4found = smbacl4_find_equal_special(acl, ace); - if (ace4found) - { - switch(acedup) - { - case e_merge: /* "merge" flags */ - *paddNewACE = False; - ace4found->aceFlags |= ace->aceFlags; - ace4found->aceMask |= ace->aceMask; - break; - case e_ignore: /* leave out this record */ - *paddNewACE = False; - break; - case e_reject: /* do an error */ - DEBUG(8, ("ACL rejected by duplicate nt ace#%d\n", i)); - errno = EINVAL; /* SHOULD be set on any _real_ error */ - result = -1; - break; - default: - break; - } - } - return result; -} - -static SMB4ACL_T *smbacl4_win2nfs4( - SEC_ACL *dacl, - smbacl4_vfs_params *pparams, - uid_t ownerUID, - gid_t ownerGID -) -{ - SMB4ACL_T *acl; - uint32 i; - TALLOC_CTX *mem_ctx = main_loop_talloc_get(); - - DEBUG(10, ("smbacl4_win2nfs4 invoked\n")); - - acl = smb_create_smb4acl(); - if (acl==NULL) - return NULL; - - for(i=0; inum_aces; i++) { - SMB_ACE4PROP_T ace_v4; - BOOL addNewACE = True; - - if (smbacl4_fill_ace4(mem_ctx, pparams, ownerUID, ownerGID, - dacl->ace + i, &ace_v4)) - return NULL; - - if (pparams->acedup!=e_dontcare) { - if (smbacl4_MergeIgnoreReject(pparams->acedup, acl, - &ace_v4, &addNewACE, i)) - return NULL; - } - - if (addNewACE) - smb_add_ace4(acl, &ace_v4); - } - - return acl; -} - -BOOL smb_set_nt_acl_nfs4(files_struct *fsp, - uint32 security_info_sent, - SEC_DESC *psd, - set_nfs4acl_native_fn_t set_nfs4_native) -{ - smbacl4_vfs_params params; - SMB4ACL_T *acl = NULL; - BOOL result; - - SMB_STRUCT_STAT sbuf; - BOOL need_chown = False; - uid_t newUID = (uid_t)-1; - gid_t newGID = (gid_t)-1; - - DEBUG(10, ("smb_set_nt_acl_nfs4 invoked for %s\n", fsp->fsp_name)); - - if ((security_info_sent & (DACL_SECURITY_INFORMATION | - GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION)) == 0) - { - DEBUG(9, ("security_info_sent (0x%x) ignored\n", - security_info_sent)); - return True; /* won't show error - later to be refined... */ - } - - /* Special behaviours */ - if (smbacl4_get_vfs_params(SMBACL4_PARAM_TYPE_NAME, fsp, ¶ms)) - return False; - - if (smbacl4_GetFileOwner(fsp, &sbuf)) - return False; - - /* chown logic is a copy/paste from posix_acl.c:set_nt_acl */ - if (!unpack_nt_owners(SNUM(fsp->conn), &newUID, &newGID, security_info_sent, psd)) - { - DEBUG(8, ("unpack_nt_owners failed")); - return False; - } - if (((newUID != (uid_t)-1) && (sbuf.st_uid != newUID)) || - ((newGID != (gid_t)-1) && (sbuf.st_gid != newGID))) { - need_chown = True; - } - if (need_chown) { - if ((newUID == (uid_t)-1 || newUID == current_user.ut.uid)) { - if(try_chown(fsp->conn, fsp->fsp_name, newUID, newGID)) { - DEBUG(3,("chown %s, %u, %u failed. Error = %s.\n", - fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID, strerror(errno) )); - return False; - } - DEBUG(10,("chown %s, %u, %u succeeded.\n", - fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID)); - if (smbacl4_GetFileOwner(fsp, &sbuf)) - return False; - need_chown = False; - } else { /* chown is needed, but _after_ changing acl */ - sbuf.st_uid = newUID; /* OWNER@ in case of e_special */ - sbuf.st_gid = newGID; /* GROUP@ in case of e_special */ - } - } - - if ((security_info_sent & DACL_SECURITY_INFORMATION)!=0 && psd->dacl!=NULL) - { - acl = smbacl4_win2nfs4(psd->dacl, ¶ms, sbuf.st_uid, sbuf.st_gid); - if (!acl) - return False; - - smbacl4_dump_nfs4acl(10, acl); - - result = set_nfs4_native(fsp, acl); - if (result!=True) - { - DEBUG(10, ("set_nfs4_native failed with %s\n", strerror(errno))); - return False; - } - } else - DEBUG(10, ("no dacl found; security_info_sent = 0x%x\n", security_info_sent)); - - /* Any chown pending? */ - if (need_chown) { - DEBUG(3,("chown#2 %s. uid = %u, gid = %u.\n", - fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID)); - if (try_chown(fsp->conn, fsp->fsp_name, newUID, newGID)) { - DEBUG(2,("chown#2 %s, %u, %u failed. Error = %s.\n", - fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID, - strerror(errno))); - return False; - } - DEBUG(10,("chown#2 %s, %u, %u succeeded.\n", - fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID)); - } - - DEBUG(10, ("smb_set_nt_acl_nfs4 succeeded\n")); - return True; -- cgit From 8155621d54c7385a60274b30572770bd4f17e504 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 18 Sep 2006 02:27:48 +0000 Subject: r18603: Add in the NFSv4 ACL mapping code from IBM. Sorry for the delay :-). Jeremy. (This used to be commit a52fa218952ffcd784ea31e947aa4d17dfdc8ee0) --- source3/modules/nfs4_acls.c | 668 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 668 insertions(+) create mode 100644 source3/modules/nfs4_acls.c (limited to 'source3/modules/nfs4_acls.c') diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c new file mode 100644 index 0000000000..5daab41b45 --- /dev/null +++ b/source3/modules/nfs4_acls.c @@ -0,0 +1,668 @@ +/* + * NFS4 ACL handling + * + * Copyright (C) Jim McDonough, 2006 + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" +#include "nfs4_acls.h" + +#define SMBACL4_PARAM_TYPE_NAME "nfs4" + +#define SMB_ACE4_INT_MAGIC 0x76F8A967 +typedef struct _SMB_ACE4_INT_T +{ + uint32 magic; + SMB_ACE4PROP_T prop; + void *next; +} SMB_ACE4_INT_T; + +#define SMB_ACL4_INT_MAGIC 0x29A3E792 +typedef struct _SMB_ACL4_INT_T +{ + uint32 magic; + uint32 naces; + SMB_ACE4_INT_T *first; + SMB_ACE4_INT_T *last; +} SMB_ACL4_INT_T; + +extern struct current_user current_user; +extern int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid); +extern BOOL unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, + uint32 security_info_sent, SEC_DESC *psd); + +static SMB_ACL4_INT_T *get_validated_aclint(SMB4ACL_T *acl) +{ + SMB_ACL4_INT_T *aclint = (SMB_ACL4_INT_T *)acl; + if (acl==NULL) + { + DEBUG(2, ("acl is NULL\n")); + errno = EINVAL; + return NULL; + } + if (aclint->magic!=SMB_ACL4_INT_MAGIC) + { + DEBUG(2, ("aclint bad magic 0x%x\n", aclint->magic)); + errno = EINVAL; + return NULL; + } + return aclint; +} + +static SMB_ACE4_INT_T *get_validated_aceint(SMB4ACE_T *ace) +{ + SMB_ACE4_INT_T *aceint = (SMB_ACE4_INT_T *)ace; + if (ace==NULL) + { + DEBUG(2, ("ace is NULL\n")); + errno = EINVAL; + return NULL; + } + if (aceint->magic!=SMB_ACE4_INT_MAGIC) + { + DEBUG(2, ("aceint bad magic 0x%x\n", aceint->magic)); + errno = EINVAL; + return NULL; + } + return aceint; +} + +SMB4ACL_T *smb_create_smb4acl(void) +{ + TALLOC_CTX *mem_ctx = main_loop_talloc_get(); + SMB_ACL4_INT_T *acl = (SMB_ACL4_INT_T *)talloc_size(mem_ctx, sizeof(SMB_ACL4_INT_T)); + if (acl==NULL) + { + DEBUG(0, ("talloc_size failed\n")); + errno = ENOMEM; + return NULL; + } + memset(acl, 0, sizeof(SMB_ACL4_INT_T)); + acl->magic = SMB_ACL4_INT_MAGIC; + /* acl->first, last = NULL not needed */ + return (SMB4ACL_T *)acl; +} + +SMB4ACE_T *smb_add_ace4(SMB4ACL_T *acl, SMB_ACE4PROP_T *prop) +{ + SMB_ACL4_INT_T *aclint = get_validated_aclint(acl); + TALLOC_CTX *mem_ctx = main_loop_talloc_get(); + SMB_ACE4_INT_T *ace; + + ace = (SMB_ACE4_INT_T *)talloc_size(mem_ctx, sizeof(SMB_ACE4_INT_T)); + if (ace==NULL) + { + DEBUG(0, ("talloc_size failed\n")); + errno = ENOMEM; + return NULL; + } + memset(ace, 0, sizeof(SMB_ACE4_INT_T)); + ace->magic = SMB_ACE4_INT_MAGIC; + /* ace->next = NULL not needed */ + memcpy(&ace->prop, prop, sizeof(SMB_ACE4PROP_T)); + + if (aclint->first==NULL) + { + aclint->first = ace; + aclint->last = ace; + } else { + aclint->last->next = (void *)ace; + aclint->last = ace; + } + aclint->naces++; + + return (SMB4ACE_T *)ace; +} + +SMB_ACE4PROP_T *smb_get_ace4(SMB4ACE_T *ace) +{ + SMB_ACE4_INT_T *aceint = get_validated_aceint(ace); + if (aceint==NULL) + return NULL; + + return &aceint->prop; +} + +SMB4ACE_T *smb_next_ace4(SMB4ACE_T *ace) +{ + SMB_ACE4_INT_T *aceint = get_validated_aceint(ace); + if (aceint==NULL) + return NULL; + + return (SMB4ACE_T *)aceint->next; +} + +SMB4ACE_T *smb_first_ace4(SMB4ACL_T *acl) +{ + SMB_ACL4_INT_T *aclint = get_validated_aclint(acl); + if (aclint==NULL) + return NULL; + + return (SMB4ACE_T *)aclint->first; +} + +uint32 smb_get_naces(SMB4ACL_T *acl) +{ + SMB_ACL4_INT_T *aclint = get_validated_aclint(acl); + if (aclint==NULL) + return 0; + + return aclint->naces; +} + +static int smbacl4_GetFileOwner(files_struct *fsp, SMB_STRUCT_STAT *psbuf) +{ + memset(psbuf, 0, sizeof(SMB_STRUCT_STAT)); + if (fsp->is_directory || fsp->fh->fd == -1) { + /* Get the stat struct for the owner info. */ + if (SMB_VFS_STAT(fsp->conn,fsp->fsp_name, psbuf) != 0) + { + DEBUG(8, ("SMB_VFS_STAT failed with error %s\n", + strerror(errno))); + return -1; + } + } else { + if (SMB_VFS_FSTAT(fsp,fsp->fh->fd, psbuf) != 0) + { + DEBUG(8, ("SMB_VFS_FSTAT failed with error %s\n", + strerror(errno))); + return -1; + } + } + + return 0; +} + +static BOOL smbacl4_nfs42win(SMB4ACL_T *acl, /* in */ + DOM_SID *psid_owner, /* in */ + DOM_SID *psid_group, /* in */ + SEC_ACE **ppnt_ace_list, /* out */ + int *pgood_aces /* out */ +) +{ + SMB_ACL4_INT_T *aclint = (SMB_ACL4_INT_T *)acl; + SMB_ACE4_INT_T *aceint; + SEC_ACE *nt_ace_list = NULL; + int good_aces = 0; + TALLOC_CTX *mem_ctx = main_loop_talloc_get(); + + DEBUG(10, ("smbacl_nfs42win entered")); + + aclint = get_validated_aclint(acl); + if (aclint==NULL) + return False; + + nt_ace_list = (SEC_ACE *)talloc_size(mem_ctx, aclint->naces * sizeof(SEC_ACE)); + if (nt_ace_list==NULL) + { + DEBUG(10, ("talloc error")); + errno = ENOMEM; + return False; + } + memset(nt_ace_list, 0, aclint->naces * sizeof(SEC_ACE)); + + for (aceint=aclint->first; aceint!=NULL; aceint=(SMB_ACE4_INT_T *)aceint->next) { + SEC_ACCESS mask; + DOM_SID sid; + SMB_ACE4PROP_T *ace = &aceint->prop; + + DEBUG(10, ("magic: 0x%x, type: %d, iflags: %x, flags: %x, mask: %x, " + "who: %d\n", aceint->magic, ace->aceType, ace->flags, + ace->aceFlags, ace->aceMask, ace->who.id)); + + SMB_ASSERT(aceint->magic==SMB_ACE4_INT_MAGIC); + + if (ace->flags & SMB_ACE4_ID_SPECIAL) { + switch (ace->who.special_id) { + case SMB_ACE4_WHO_OWNER: + sid_copy(&sid, psid_owner); + break; + case SMB_ACE4_WHO_GROUP: + sid_copy(&sid, psid_group); + break; + case SMB_ACE4_WHO_EVERYONE: + sid_copy(&sid, &global_sid_World); + break; + default: + DEBUG(8, ("invalid special who id %d " + "ignored\n", ace->who.special_id)); + } + } else { + if (ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) { + gid_to_sid(&sid, ace->who.gid); + } else { + uid_to_sid(&sid, ace->who.uid); + } + } + DEBUG(10, ("mapped %d to %s\n", ace->who.id, + sid_string_static(&sid))); + + init_sec_access(&mask, ace->aceMask); + init_sec_ace(&nt_ace_list[good_aces++], &sid, + ace->aceType, mask, + ace->aceFlags & 0xf); + } + + *ppnt_ace_list = nt_ace_list; + *pgood_aces = good_aces; + + return True; +} + +size_t smb_get_nt_acl_nfs4(files_struct *fsp, + uint32 security_info, + SEC_DESC **ppdesc, SMB4ACL_T *acl) +{ + int good_aces = 0; + SMB_STRUCT_STAT sbuf; + DOM_SID sid_owner, sid_group; + size_t sd_size = 0; + SEC_ACE *nt_ace_list = NULL; + SEC_ACL *psa = NULL; + TALLOC_CTX *mem_ctx = main_loop_talloc_get(); + + DEBUG(10, ("smb_get_nt_acl_nfs4 invoked for %s\n", fsp->fsp_name)); + + if (acl==NULL || smb_get_naces(acl)==0) + return 0; /* special because we shouldn't alloc 0 for win */ + + if (smbacl4_GetFileOwner(fsp, &sbuf)) + return 0; + + uid_to_sid(&sid_owner, sbuf.st_uid); + gid_to_sid(&sid_group, sbuf.st_gid); + + if (smbacl4_nfs42win(acl, + &sid_owner, + &sid_group, + &nt_ace_list, + &good_aces + )==False) { + DEBUG(8,("smbacl4_nfs42win failed\n")); + return 0; + } + + psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, + good_aces, nt_ace_list); + if (psa == NULL) { + DEBUG(2,("make_sec_acl failed\n")); + return 0; + } + + DEBUG(10,("after make sec_acl\n")); + *ppdesc = make_sec_desc(mem_ctx, SEC_DESC_REVISION, + SEC_DESC_SELF_RELATIVE, + (security_info & OWNER_SECURITY_INFORMATION) + ? &sid_owner : NULL, + (security_info & GROUP_SECURITY_INFORMATION) + ? &sid_group : NULL, + NULL, psa, &sd_size); + if (*ppdesc==NULL) { + DEBUG(2,("make_sec_desc failed\n")); + return 0; + } + + DEBUG(10, ("smb_get_nt_acl_nfs4 successfully exited with sd_size %d\n", sd_size)); + return sd_size; +} + +enum smbacl4_mode_enum {e_simple=0, e_special=1}; +enum smbacl4_acedup_enum {e_dontcare=0, e_reject=1, e_ignore=2, e_merge=3}; + +typedef struct _smbacl4_vfs_params { + enum smbacl4_mode_enum mode; + BOOL do_chown; + enum smbacl4_acedup_enum acedup; +} smbacl4_vfs_params; + +/* + * Gather special parameters for NFS4 ACL handling + */ +static int smbacl4_get_vfs_params( + const char *type_name, + files_struct *fsp, + smbacl4_vfs_params *params +) +{ + static const struct enum_list enum_smbacl4_modes[] = { + { e_simple, "simple" }, + { e_special, "special" } + }; + static const struct enum_list enum_smbacl4_acedups[] = { + { e_dontcare, "dontcare" }, + { e_reject, "reject" }, + { e_ignore, "ignore" }, + { e_merge, "merge" }, + }; + + memset(params, 0, sizeof(smbacl4_vfs_params)); + params->mode = (enum smbacl4_mode_enum)lp_parm_enum( + SNUM(fsp->conn), type_name, + "mode", enum_smbacl4_modes, e_simple); + params->do_chown = lp_parm_bool(SNUM(fsp->conn), type_name, + "chown", True); + params->acedup = (enum smbacl4_acedup_enum)lp_parm_enum( + SNUM(fsp->conn), type_name, + "acedup", enum_smbacl4_acedups, e_dontcare); + + DEBUG(10, ("mode:%s, do_chown:%s, acedup: %s\n", + enum_smbacl4_modes[params->mode].name, + params->do_chown ? "true" : "false", + enum_smbacl4_acedups[params->acedup].name)); + + return 0; +} + +static void smbacl4_dump_nfs4acl(int level, SMB4ACL_T *acl) +{ + SMB_ACL4_INT_T *aclint = get_validated_aclint(acl); + SMB_ACE4_INT_T *aceint; + + DEBUG(level, ("NFS4ACL: size=%d\n", aclint->naces)); + + for(aceint = aclint->first; aceint!=NULL; aceint=(SMB_ACE4_INT_T *)aceint->next) { + SMB_ACE4PROP_T *ace = &aceint->prop; + + DEBUG(level, ("\tACE: type=%d, flags=0x%x, fflags=0x%x, mask=0x%x, id=%d\n", + ace->aceType, + ace->aceFlags, ace->flags, + ace->aceMask, + ace->who.id)); + } +} + +/* + * Find 2 NFS4 who-special ACE property (non-copy!!!) + * match nonzero if "special" and who is equal + * return ace if found matching; otherwise NULL + */ +static SMB_ACE4PROP_T *smbacl4_find_equal_special( + SMB4ACL_T *acl, + SMB_ACE4PROP_T *aceNew) +{ + SMB_ACL4_INT_T *aclint = get_validated_aclint(acl); + SMB_ACE4_INT_T *aceint; + + for(aceint = aclint->first; aceint!=NULL; aceint=(SMB_ACE4_INT_T *)aceint->next) { + SMB_ACE4PROP_T *ace = &aceint->prop; + + if (ace->flags == aceNew->flags && + ace->aceType==aceNew->aceType && + (ace->aceFlags&SMB_ACE4_IDENTIFIER_GROUP)== + (aceNew->aceFlags&SMB_ACE4_IDENTIFIER_GROUP) + ) { + /* keep type safety; e.g. gid is an u.short */ + if (ace->flags & SMB_ACE4_ID_SPECIAL) + { + if (ace->who.special_id==aceNew->who.special_id) + return ace; + } else { + if (ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) + { + if (ace->who.gid==aceNew->who.gid) + return ace; + } else { + if (ace->who.uid==aceNew->who.uid) + return ace; + } + } + } + } + + return NULL; +} + +static int smbacl4_fill_ace4( + TALLOC_CTX *mem_ctx, + smbacl4_vfs_params *params, + uid_t ownerUID, + gid_t ownerGID, + SEC_ACE *ace_nt, /* input */ + SMB_ACE4PROP_T *ace_v4 /* output */ +) +{ + const char *dom, *name; + enum SID_NAME_USE type; + uid_t uid; + gid_t gid; + + DEBUG(10, ("got ace for %s\n", + sid_string_static(&ace_nt->trustee))); + + memset(ace_v4, 0, sizeof(SMB_ACE4PROP_T)); + ace_v4->aceType = ace_nt->type; /* only ACCES|DENY supported right now */ + ace_v4->aceFlags = ace_nt->flags & SEC_ACE_FLAG_VALID_INHERIT; + ace_v4->aceMask = ace_nt->info.mask & + (STD_RIGHT_ALL_ACCESS | SA_RIGHT_FILE_ALL_ACCESS); + + if (ace_v4->aceFlags!=ace_nt->flags) + DEBUG(9, ("ace_v4->aceFlags(0x%x)!=ace_nt->flags(0x%x)\n", + ace_v4->aceFlags, ace_nt->flags)); + + if (ace_v4->aceMask!=ace_nt->info.mask) + DEBUG(9, ("ace_v4->aceMask(0x%x)!=ace_nt->info.mask(0x%x)\n", + ace_v4->aceMask, ace_nt->info.mask)); + + if (sid_equal(&ace_nt->trustee, &global_sid_World)) { + ace_v4->who.special_id = SMB_ACE4_WHO_EVERYONE; + ace_v4->flags |= SMB_ACE4_ID_SPECIAL; + } else { + if (!lookup_sid(mem_ctx, &ace_nt->trustee, &dom, &name, &type)) { + DEBUG(8, ("Could not find %s' type\n", + sid_string_static(&ace_nt->trustee))); + errno = EINVAL; + return -1; + } + + if (type == SID_NAME_USER) { + if (!sid_to_uid(&ace_nt->trustee, &uid)) { + DEBUG(2, ("Could not convert %s to uid\n", + sid_string_static(&ace_nt->trustee))); + return -1; + } + + if (params->mode==e_special && uid==ownerUID) { + ace_v4->flags |= SMB_ACE4_ID_SPECIAL; + ace_v4->who.special_id = SMB_ACE4_WHO_OWNER; + } else { + ace_v4->who.uid = uid; + } + } else { /* else group? - TODO check it... */ + if (!sid_to_gid(&ace_nt->trustee, &gid)) { + DEBUG(2, ("Could not convert %s to gid\n", + sid_string_static(&ace_nt->trustee))); + return -1; + } + ace_v4->aceFlags |= SMB_ACE4_IDENTIFIER_GROUP; + + if (params->mode==e_special && gid==ownerGID) { + ace_v4->flags |= SMB_ACE4_ID_SPECIAL; + ace_v4->who.special_id = SMB_ACE4_WHO_GROUP; + } else { + ace_v4->who.gid = gid; + } + } + } + + return 0; /* OK */ +} + +static int smbacl4_MergeIgnoreReject( + enum smbacl4_acedup_enum acedup, + SMB4ACL_T *acl, /* may modify it */ + SMB_ACE4PROP_T *ace, /* the "new" ACE */ + BOOL *paddNewACE, + int i +) +{ + int result = 0; + SMB_ACE4PROP_T *ace4found = smbacl4_find_equal_special(acl, ace); + if (ace4found) + { + switch(acedup) + { + case e_merge: /* "merge" flags */ + *paddNewACE = False; + ace4found->aceFlags |= ace->aceFlags; + ace4found->aceMask |= ace->aceMask; + break; + case e_ignore: /* leave out this record */ + *paddNewACE = False; + break; + case e_reject: /* do an error */ + DEBUG(8, ("ACL rejected by duplicate nt ace#%d\n", i)); + errno = EINVAL; /* SHOULD be set on any _real_ error */ + result = -1; + break; + default: + break; + } + } + return result; +} + +static SMB4ACL_T *smbacl4_win2nfs4( + SEC_ACL *dacl, + smbacl4_vfs_params *pparams, + uid_t ownerUID, + gid_t ownerGID +) +{ + SMB4ACL_T *acl; + uint32 i; + TALLOC_CTX *mem_ctx = main_loop_talloc_get(); + + DEBUG(10, ("smbacl4_win2nfs4 invoked\n")); + + acl = smb_create_smb4acl(); + if (acl==NULL) + return NULL; + + for(i=0; inum_aces; i++) { + SMB_ACE4PROP_T ace_v4; + BOOL addNewACE = True; + + if (smbacl4_fill_ace4(mem_ctx, pparams, ownerUID, ownerGID, + dacl->ace + i, &ace_v4)) + return NULL; + + if (pparams->acedup!=e_dontcare) { + if (smbacl4_MergeIgnoreReject(pparams->acedup, acl, + &ace_v4, &addNewACE, i)) + return NULL; + } + + if (addNewACE) + smb_add_ace4(acl, &ace_v4); + } + + return acl; +} + +BOOL smb_set_nt_acl_nfs4(files_struct *fsp, + uint32 security_info_sent, + SEC_DESC *psd, + set_nfs4acl_native_fn_t set_nfs4_native) +{ + smbacl4_vfs_params params; + SMB4ACL_T *acl = NULL; + BOOL result; + + SMB_STRUCT_STAT sbuf; + BOOL need_chown = False; + uid_t newUID = (uid_t)-1; + gid_t newGID = (gid_t)-1; + + DEBUG(10, ("smb_set_nt_acl_nfs4 invoked for %s\n", fsp->fsp_name)); + + if ((security_info_sent & (DACL_SECURITY_INFORMATION | + GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION)) == 0) + { + DEBUG(9, ("security_info_sent (0x%x) ignored\n", + security_info_sent)); + return True; /* won't show error - later to be refined... */ + } + + /* Special behaviours */ + if (smbacl4_get_vfs_params(SMBACL4_PARAM_TYPE_NAME, fsp, ¶ms)) + return False; + + if (smbacl4_GetFileOwner(fsp, &sbuf)) + return False; + + /* chown logic is a copy/paste from posix_acl.c:set_nt_acl */ + if (!unpack_nt_owners(SNUM(fsp->conn), &newUID, &newGID, security_info_sent, psd)) + { + DEBUG(8, ("unpack_nt_owners failed")); + return False; + } + if (((newUID != (uid_t)-1) && (sbuf.st_uid != newUID)) || + ((newGID != (gid_t)-1) && (sbuf.st_gid != newGID))) { + need_chown = True; + } + if (need_chown) { + if ((newUID == (uid_t)-1 || newUID == current_user.ut.uid)) { + if(try_chown(fsp->conn, fsp->fsp_name, newUID, newGID)) { + DEBUG(3,("chown %s, %u, %u failed. Error = %s.\n", + fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID, strerror(errno) )); + return False; + } + DEBUG(10,("chown %s, %u, %u succeeded.\n", + fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID)); + if (smbacl4_GetFileOwner(fsp, &sbuf)) + return False; + need_chown = False; + } else { /* chown is needed, but _after_ changing acl */ + sbuf.st_uid = newUID; /* OWNER@ in case of e_special */ + sbuf.st_gid = newGID; /* GROUP@ in case of e_special */ + } + } + + if ((security_info_sent & DACL_SECURITY_INFORMATION)!=0 && psd->dacl!=NULL) + { + acl = smbacl4_win2nfs4(psd->dacl, ¶ms, sbuf.st_uid, sbuf.st_gid); + if (!acl) + return False; + + smbacl4_dump_nfs4acl(10, acl); + + result = set_nfs4_native(fsp, acl); + if (result!=True) + { + DEBUG(10, ("set_nfs4_native failed with %s\n", strerror(errno))); + return False; + } + } else + DEBUG(10, ("no dacl found; security_info_sent = 0x%x\n", security_info_sent)); + + /* Any chown pending? */ + if (need_chown) { + DEBUG(3,("chown#2 %s. uid = %u, gid = %u.\n", + fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID)); + if (try_chown(fsp->conn, fsp->fsp_name, newUID, newGID)) { + DEBUG(2,("chown#2 %s, %u, %u failed. Error = %s.\n", + fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID, + strerror(errno))); + return False; + } + DEBUG(10,("chown#2 %s, %u, %u succeeded.\n", + fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID)); + } + + DEBUG(10, ("smb_set_nt_acl_nfs4 succeeded\n")); + return True; +} -- cgit From eb6e31afedd6f706ecc2b4d93d492132b2ee742b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 20 Sep 2006 17:09:03 +0000 Subject: r18719: Compile fix from Peter Somogyi. Jeremy. (This used to be commit 867eeaafceaebde030a1d1e2fa39950b898b1846) --- source3/modules/nfs4_acls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/modules/nfs4_acls.c') diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index 5daab41b45..caa2f9503c 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -436,7 +436,7 @@ static int smbacl4_fill_ace4( ) { const char *dom, *name; - enum SID_NAME_USE type; + enum lsa_SidType type; uid_t uid; gid_t gid; -- cgit From b3d18b12c23670b02f4f98e1afeb32f829050fb3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 21 Sep 2006 14:17:00 +0000 Subject: r18785: Check in Peter Somogyis build fix (This used to be commit 31c1be90565b2d2d111dddb7f0563fa8c303852b) --- source3/modules/nfs4_acls.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/modules/nfs4_acls.c') diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index caa2f9503c..91ebba1f58 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -446,16 +446,16 @@ static int smbacl4_fill_ace4( memset(ace_v4, 0, sizeof(SMB_ACE4PROP_T)); ace_v4->aceType = ace_nt->type; /* only ACCES|DENY supported right now */ ace_v4->aceFlags = ace_nt->flags & SEC_ACE_FLAG_VALID_INHERIT; - ace_v4->aceMask = ace_nt->info.mask & + ace_v4->aceMask = ace_nt->access_mask & (STD_RIGHT_ALL_ACCESS | SA_RIGHT_FILE_ALL_ACCESS); if (ace_v4->aceFlags!=ace_nt->flags) DEBUG(9, ("ace_v4->aceFlags(0x%x)!=ace_nt->flags(0x%x)\n", ace_v4->aceFlags, ace_nt->flags)); - if (ace_v4->aceMask!=ace_nt->info.mask) - DEBUG(9, ("ace_v4->aceMask(0x%x)!=ace_nt->info.mask(0x%x)\n", - ace_v4->aceMask, ace_nt->info.mask)); + if (ace_v4->aceMask!=ace_nt->access_mask) + DEBUG(9, ("ace_v4->aceMask(0x%x)!=ace_nt->access_mask(0x%x)\n", + ace_v4->aceMask, ace_nt->access_mask)); if (sid_equal(&ace_nt->trustee, &global_sid_World)) { ace_v4->who.special_id = SMB_ACE4_WHO_EVERYONE; @@ -557,7 +557,7 @@ static SMB4ACL_T *smbacl4_win2nfs4( BOOL addNewACE = True; if (smbacl4_fill_ace4(mem_ctx, pparams, ownerUID, ownerGID, - dacl->ace + i, &ace_v4)) + dacl->aces + i, &ace_v4)) return NULL; if (pparams->acedup!=e_dontcare) { -- cgit From 679a313517cc94e13d1be6eb6e8cc42128c8412c Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Tue, 20 Mar 2007 08:17:27 +0000 Subject: r21885: Chown logic should be activated only if nfs4:chown=yes (This used to be commit b10410634f6dac532a867be5506cf79886833828) --- source3/modules/nfs4_acls.c | 50 +++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 24 deletions(-) (limited to 'source3/modules/nfs4_acls.c') diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index 91ebba1f58..dd45240857 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -604,31 +604,33 @@ BOOL smb_set_nt_acl_nfs4(files_struct *fsp, if (smbacl4_GetFileOwner(fsp, &sbuf)) return False; - /* chown logic is a copy/paste from posix_acl.c:set_nt_acl */ - if (!unpack_nt_owners(SNUM(fsp->conn), &newUID, &newGID, security_info_sent, psd)) - { - DEBUG(8, ("unpack_nt_owners failed")); - return False; - } - if (((newUID != (uid_t)-1) && (sbuf.st_uid != newUID)) || - ((newGID != (gid_t)-1) && (sbuf.st_gid != newGID))) { - need_chown = True; - } - if (need_chown) { - if ((newUID == (uid_t)-1 || newUID == current_user.ut.uid)) { - if(try_chown(fsp->conn, fsp->fsp_name, newUID, newGID)) { - DEBUG(3,("chown %s, %u, %u failed. Error = %s.\n", - fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID, strerror(errno) )); - return False; + if (params.do_chown) { + /* chown logic is a copy/paste from posix_acl.c:set_nt_acl */ + if (!unpack_nt_owners(SNUM(fsp->conn), &newUID, &newGID, security_info_sent, psd)) + { + DEBUG(8, ("unpack_nt_owners failed")); + return False; + } + if (((newUID != (uid_t)-1) && (sbuf.st_uid != newUID)) || + ((newGID != (gid_t)-1) && (sbuf.st_gid != newGID))) { + need_chown = True; + } + if (need_chown) { + if ((newUID == (uid_t)-1 || newUID == current_user.ut.uid)) { + if(try_chown(fsp->conn, fsp->fsp_name, newUID, newGID)) { + DEBUG(3,("chown %s, %u, %u failed. Error = %s.\n", + fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID, strerror(errno) )); + return False; + } + DEBUG(10,("chown %s, %u, %u succeeded.\n", + fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID)); + if (smbacl4_GetFileOwner(fsp, &sbuf)) + return False; + need_chown = False; + } else { /* chown is needed, but _after_ changing acl */ + sbuf.st_uid = newUID; /* OWNER@ in case of e_special */ + sbuf.st_gid = newGID; /* GROUP@ in case of e_special */ } - DEBUG(10,("chown %s, %u, %u succeeded.\n", - fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID)); - if (smbacl4_GetFileOwner(fsp, &sbuf)) - return False; - need_chown = False; - } else { /* chown is needed, but _after_ changing acl */ - sbuf.st_uid = newUID; /* OWNER@ in case of e_special */ - sbuf.st_gid = newGID; /* GROUP@ in case of e_special */ } } -- cgit From 12ba88574bf91bdcc4447bfc3d429b799064bfd9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 27 Apr 2007 23:18:41 +0000 Subject: r22542: Move over to using the _strict varients of the talloc calls. No functional changes. Looks bigger than it is :-). Jeremy. (This used to be commit f6fa3080fee1b20df9f1968500840a88cf0ee592) --- source3/modules/nfs4_acls.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/modules/nfs4_acls.c') diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index dd45240857..b6bcc8cd47 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -84,10 +84,10 @@ static SMB_ACE4_INT_T *get_validated_aceint(SMB4ACE_T *ace) SMB4ACL_T *smb_create_smb4acl(void) { TALLOC_CTX *mem_ctx = main_loop_talloc_get(); - SMB_ACL4_INT_T *acl = (SMB_ACL4_INT_T *)talloc_size(mem_ctx, sizeof(SMB_ACL4_INT_T)); + SMB_ACL4_INT_T *acl = (SMB_ACL4_INT_T *)TALLOC_SIZE(mem_ctx, sizeof(SMB_ACL4_INT_T)); if (acl==NULL) { - DEBUG(0, ("talloc_size failed\n")); + DEBUG(0, ("TALLOC_SIZE failed\n")); errno = ENOMEM; return NULL; } @@ -103,10 +103,10 @@ SMB4ACE_T *smb_add_ace4(SMB4ACL_T *acl, SMB_ACE4PROP_T *prop) TALLOC_CTX *mem_ctx = main_loop_talloc_get(); SMB_ACE4_INT_T *ace; - ace = (SMB_ACE4_INT_T *)talloc_size(mem_ctx, sizeof(SMB_ACE4_INT_T)); + ace = (SMB_ACE4_INT_T *)TALLOC_SIZE(mem_ctx, sizeof(SMB_ACE4_INT_T)); if (ace==NULL) { - DEBUG(0, ("talloc_size failed\n")); + DEBUG(0, ("TALLOC_SIZE failed\n")); errno = ENOMEM; return NULL; } @@ -206,7 +206,7 @@ static BOOL smbacl4_nfs42win(SMB4ACL_T *acl, /* in */ if (aclint==NULL) return False; - nt_ace_list = (SEC_ACE *)talloc_size(mem_ctx, aclint->naces * sizeof(SEC_ACE)); + nt_ace_list = (SEC_ACE *)TALLOC_SIZE(mem_ctx, aclint->naces * sizeof(SEC_ACE)); if (nt_ace_list==NULL) { DEBUG(10, ("talloc error")); -- cgit From 09ba519eb4a2c240ca7bd6ab830e632fdc4b8c5d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 30 Apr 2007 03:41:40 +0000 Subject: r22592: Fix TALLOC_SIZE to be consistent. Jeremy. (This used to be commit 8044a6482c7c165a64878982cee5ee9756a0a734) --- source3/modules/nfs4_acls.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'source3/modules/nfs4_acls.c') diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index b6bcc8cd47..8530a5db03 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -206,14 +206,18 @@ static BOOL smbacl4_nfs42win(SMB4ACL_T *acl, /* in */ if (aclint==NULL) return False; - nt_ace_list = (SEC_ACE *)TALLOC_SIZE(mem_ctx, aclint->naces * sizeof(SEC_ACE)); - if (nt_ace_list==NULL) - { - DEBUG(10, ("talloc error")); - errno = ENOMEM; - return False; + if (aclint->naces) { + nt_ace_list = (SEC_ACE *)TALLOC_SIZE(mem_ctx, aclint->naces * sizeof(SEC_ACE)); + if (nt_ace_list==NULL) + { + DEBUG(10, ("talloc error")); + errno = ENOMEM; + return False; + } + memset(nt_ace_list, 0, aclint->naces * sizeof(SEC_ACE)); + } else { + nt_ace_list = NULL; } - memset(nt_ace_list, 0, aclint->naces * sizeof(SEC_ACE)); for (aceint=aclint->first; aceint!=NULL; aceint=(SMB_ACE4_INT_T *)aceint->next) { SEC_ACCESS mask; -- cgit From ea7f6e7afafb2da4090d02cb5eb128e3bd0ec2cd Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Sat, 2 Jun 2007 06:28:38 +0000 Subject: r23302: Refactor vfs_gpfs module, fix problems with chmod Tridge has found during ctdb tests (This used to be commit e150e42ac59494a1da12bb5c9da8c9c935780924) --- source3/modules/nfs4_acls.c | 52 +++++++++++++++------------------------------ 1 file changed, 17 insertions(+), 35 deletions(-) (limited to 'source3/modules/nfs4_acls.c') diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index 8530a5db03..1da8d1b7a3 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -84,14 +84,13 @@ static SMB_ACE4_INT_T *get_validated_aceint(SMB4ACE_T *ace) SMB4ACL_T *smb_create_smb4acl(void) { TALLOC_CTX *mem_ctx = main_loop_talloc_get(); - SMB_ACL4_INT_T *acl = (SMB_ACL4_INT_T *)TALLOC_SIZE(mem_ctx, sizeof(SMB_ACL4_INT_T)); + SMB_ACL4_INT_T *acl = (SMB_ACL4_INT_T *)TALLOC_ZERO_SIZE(mem_ctx, sizeof(SMB_ACL4_INT_T)); if (acl==NULL) { DEBUG(0, ("TALLOC_SIZE failed\n")); errno = ENOMEM; return NULL; } - memset(acl, 0, sizeof(SMB_ACL4_INT_T)); acl->magic = SMB_ACL4_INT_MAGIC; /* acl->first, last = NULL not needed */ return (SMB4ACL_T *)acl; @@ -103,14 +102,13 @@ SMB4ACE_T *smb_add_ace4(SMB4ACL_T *acl, SMB_ACE4PROP_T *prop) TALLOC_CTX *mem_ctx = main_loop_talloc_get(); SMB_ACE4_INT_T *ace; - ace = (SMB_ACE4_INT_T *)TALLOC_SIZE(mem_ctx, sizeof(SMB_ACE4_INT_T)); + ace = (SMB_ACE4_INT_T *)TALLOC_ZERO_SIZE(mem_ctx, sizeof(SMB_ACE4_INT_T)); if (ace==NULL) { DEBUG(0, ("TALLOC_SIZE failed\n")); errno = ENOMEM; return NULL; } - memset(ace, 0, sizeof(SMB_ACE4_INT_T)); ace->magic = SMB_ACE4_INT_MAGIC; /* ace->next = NULL not needed */ memcpy(&ace->prop, prop, sizeof(SMB_ACE4PROP_T)); @@ -187,7 +185,7 @@ static int smbacl4_GetFileOwner(files_struct *fsp, SMB_STRUCT_STAT *psbuf) return 0; } -static BOOL smbacl4_nfs42win(SMB4ACL_T *acl, /* in */ +static BOOL smbacl4_nfs42win(TALLOC_CTX *mem_ctx, SMB4ACL_T *acl, /* in */ DOM_SID *psid_owner, /* in */ DOM_SID *psid_group, /* in */ SEC_ACE **ppnt_ace_list, /* out */ @@ -198,25 +196,18 @@ static BOOL smbacl4_nfs42win(SMB4ACL_T *acl, /* in */ SMB_ACE4_INT_T *aceint; SEC_ACE *nt_ace_list = NULL; int good_aces = 0; - TALLOC_CTX *mem_ctx = main_loop_talloc_get(); DEBUG(10, ("smbacl_nfs42win entered")); aclint = get_validated_aclint(acl); - if (aclint==NULL) + /* We do not check for naces being 0 or acl being NULL here because it is done upstream */ + /* in smb_get_nt_acl_nfs4(). */ + nt_ace_list = (SEC_ACE *)TALLOC_ZERO_SIZE(mem_ctx, aclint->naces * sizeof(SEC_ACE)); + if (nt_ace_list==NULL) + { + DEBUG(10, ("talloc error")); + errno = ENOMEM; return False; - - if (aclint->naces) { - nt_ace_list = (SEC_ACE *)TALLOC_SIZE(mem_ctx, aclint->naces * sizeof(SEC_ACE)); - if (nt_ace_list==NULL) - { - DEBUG(10, ("talloc error")); - errno = ENOMEM; - return False; - } - memset(nt_ace_list, 0, aclint->naces * sizeof(SEC_ACE)); - } else { - nt_ace_list = NULL; } for (aceint=aclint->first; aceint!=NULL; aceint=(SMB_ACE4_INT_T *)aceint->next) { @@ -290,31 +281,22 @@ size_t smb_get_nt_acl_nfs4(files_struct *fsp, uid_to_sid(&sid_owner, sbuf.st_uid); gid_to_sid(&sid_group, sbuf.st_gid); - if (smbacl4_nfs42win(acl, - &sid_owner, - &sid_group, - &nt_ace_list, - &good_aces - )==False) { + if (smbacl4_nfs42win(mem_ctx, acl, &sid_owner, &sid_group, &nt_ace_list, &good_aces)==False) { DEBUG(8,("smbacl4_nfs42win failed\n")); return 0; } - psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, - good_aces, nt_ace_list); + psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, good_aces, nt_ace_list); if (psa == NULL) { DEBUG(2,("make_sec_acl failed\n")); return 0; } DEBUG(10,("after make sec_acl\n")); - *ppdesc = make_sec_desc(mem_ctx, SEC_DESC_REVISION, - SEC_DESC_SELF_RELATIVE, - (security_info & OWNER_SECURITY_INFORMATION) - ? &sid_owner : NULL, - (security_info & GROUP_SECURITY_INFORMATION) - ? &sid_group : NULL, - NULL, psa, &sd_size); + *ppdesc = make_sec_desc(mem_ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, + (security_info & OWNER_SECURITY_INFORMATION) ? &sid_owner : NULL, + (security_info & GROUP_SECURITY_INFORMATION) ? &sid_group : NULL, + NULL, psa, &sd_size); if (*ppdesc==NULL) { DEBUG(2,("make_sec_desc failed\n")); return 0; @@ -448,7 +430,7 @@ static int smbacl4_fill_ace4( sid_string_static(&ace_nt->trustee))); memset(ace_v4, 0, sizeof(SMB_ACE4PROP_T)); - ace_v4->aceType = ace_nt->type; /* only ACCES|DENY supported right now */ + ace_v4->aceType = ace_nt->type; /* only ACCESS|DENY supported right now */ ace_v4->aceFlags = ace_nt->flags & SEC_ACE_FLAG_VALID_INHERIT; ace_v4->aceMask = ace_nt->access_mask & (STD_RIGHT_ALL_ACCESS | SA_RIGHT_FILE_ALL_ACCESS); -- cgit From a0ac7a7f4c0290787cdadb5866272cee2bd61b8a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 26 Jun 2007 22:49:10 +0000 Subject: r23620: Convert set_nt_acl to return NTSTATUS. Also fix the chown return to correctly return NT_STATUS_INVALID_OWNER if it should be disallowed. Matches better what W2K3R3 does. NFSv4 ACL module owners, please examine these changes. Jeremy. (This used to be commit fc6899a5506b272f8cd5f5837ca13300b4e69a5f) --- source3/modules/nfs4_acls.c | 65 +++++++++++++++------------------------------ 1 file changed, 22 insertions(+), 43 deletions(-) (limited to 'source3/modules/nfs4_acls.c') diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index 1da8d1b7a3..30c209dd93 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -42,7 +42,7 @@ typedef struct _SMB_ACL4_INT_T extern struct current_user current_user; extern int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid); -extern BOOL unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, +extern NTSTATUS unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, SEC_DESC *psd); static SMB_ACL4_INT_T *get_validated_aclint(SMB4ACL_T *acl) @@ -559,7 +559,7 @@ static SMB4ACL_T *smbacl4_win2nfs4( return acl; } -BOOL smb_set_nt_acl_nfs4(files_struct *fsp, +NTSTATUS smb_set_nt_acl_nfs4(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd, set_nfs4acl_native_fn_t set_nfs4_native) @@ -569,7 +569,6 @@ BOOL smb_set_nt_acl_nfs4(files_struct *fsp, BOOL result; SMB_STRUCT_STAT sbuf; - BOOL need_chown = False; uid_t newUID = (uid_t)-1; gid_t newGID = (gid_t)-1; @@ -580,43 +579,37 @@ BOOL smb_set_nt_acl_nfs4(files_struct *fsp, { DEBUG(9, ("security_info_sent (0x%x) ignored\n", security_info_sent)); - return True; /* won't show error - later to be refined... */ + return NT_STATUS_OK; /* won't show error - later to be refined... */ } /* Special behaviours */ if (smbacl4_get_vfs_params(SMBACL4_PARAM_TYPE_NAME, fsp, ¶ms)) - return False; + return NT_STATUS_NO_MEMORY; if (smbacl4_GetFileOwner(fsp, &sbuf)) - return False; + return map_nt_error_from_unix(errno); if (params.do_chown) { /* chown logic is a copy/paste from posix_acl.c:set_nt_acl */ - if (!unpack_nt_owners(SNUM(fsp->conn), &newUID, &newGID, security_info_sent, psd)) - { + NTSTATUS status = unpack_nt_owners(SNUM(fsp->conn), &newUID, &newGID, security_info_sent, psd); + if (!NT_STATUS_IS_OK(status)) { DEBUG(8, ("unpack_nt_owners failed")); - return False; + return status; } if (((newUID != (uid_t)-1) && (sbuf.st_uid != newUID)) || - ((newGID != (gid_t)-1) && (sbuf.st_gid != newGID))) { - need_chown = True; - } - if (need_chown) { - if ((newUID == (uid_t)-1 || newUID == current_user.ut.uid)) { - if(try_chown(fsp->conn, fsp->fsp_name, newUID, newGID)) { - DEBUG(3,("chown %s, %u, %u failed. Error = %s.\n", - fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID, strerror(errno) )); - return False; + ((newGID != (gid_t)-1) && (sbuf.st_gid != newGID))) { + if(try_chown(fsp->conn, fsp->fsp_name, newUID, newGID)) { + DEBUG(3,("chown %s, %u, %u failed. Error = %s.\n", + fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID, strerror(errno) )); + if (errno == EPERM) { + return NT_STATUS_INVALID_OWNER; } - DEBUG(10,("chown %s, %u, %u succeeded.\n", - fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID)); - if (smbacl4_GetFileOwner(fsp, &sbuf)) - return False; - need_chown = False; - } else { /* chown is needed, but _after_ changing acl */ - sbuf.st_uid = newUID; /* OWNER@ in case of e_special */ - sbuf.st_gid = newGID; /* GROUP@ in case of e_special */ + return map_nt_error_from_unix(errno); } + DEBUG(10,("chown %s, %u, %u succeeded.\n", + fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID)); + if (smbacl4_GetFileOwner(fsp, &sbuf)) + return map_nt_error_from_unix(errno); } } @@ -624,7 +617,7 @@ BOOL smb_set_nt_acl_nfs4(files_struct *fsp, { acl = smbacl4_win2nfs4(psd->dacl, ¶ms, sbuf.st_uid, sbuf.st_gid); if (!acl) - return False; + return map_nt_error_from_unix(errno); smbacl4_dump_nfs4acl(10, acl); @@ -632,25 +625,11 @@ BOOL smb_set_nt_acl_nfs4(files_struct *fsp, if (result!=True) { DEBUG(10, ("set_nfs4_native failed with %s\n", strerror(errno))); - return False; + return map_nt_error_from_unix(errno); } } else DEBUG(10, ("no dacl found; security_info_sent = 0x%x\n", security_info_sent)); - /* Any chown pending? */ - if (need_chown) { - DEBUG(3,("chown#2 %s. uid = %u, gid = %u.\n", - fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID)); - if (try_chown(fsp->conn, fsp->fsp_name, newUID, newGID)) { - DEBUG(2,("chown#2 %s, %u, %u failed. Error = %s.\n", - fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID, - strerror(errno))); - return False; - } - DEBUG(10,("chown#2 %s, %u, %u succeeded.\n", - fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID)); - } - DEBUG(10, ("smb_set_nt_acl_nfs4 succeeded\n")); - return True; + return NT_STATUS_OK; } -- cgit From d824b98f80ba186030cbb70b3a1e5daf80469ecd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 9 Jul 2007 19:25:36 +0000 Subject: r23779: Change from v2 or later to v3 or later. Jeremy. (This used to be commit 407e6e695b8366369b7c76af1ff76869b45347b3) --- source3/modules/nfs4_acls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/modules/nfs4_acls.c') diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index 30c209dd93..f29492aeff 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -5,7 +5,7 @@ * * 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 2 of the License, or + * 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, -- cgit From 153cfb9c83534b09f15cc16205d7adb19b394928 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Jul 2007 05:23:25 +0000 Subject: r23801: The FSF has moved around a lot. This fixes their Mass Ave address. (This used to be commit 87c91e4362c51819032bfbebbb273c52e203b227) --- source3/modules/nfs4_acls.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/modules/nfs4_acls.c') diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index f29492aeff..200f87a559 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -14,8 +14,7 @@ * 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, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * along with this program; if not, see . */ #include "includes.h" -- cgit From 929e1d99209e20a9c2c95c8bdfc8eaa37b2c2291 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 30 Aug 2007 19:48:31 +0000 Subject: r24809: Consolidate the use of temporary talloc contexts. This adds the two functions talloc_stackframe() and talloc_tos(). * When a new talloc stackframe is allocated with talloc_stackframe(), then * the TALLOC_CTX returned with talloc_tos() is reset to that new * frame. Whenever that stack frame is TALLOC_FREE()'ed, then the reverse * happens: The previous talloc_tos() is restored. * * This API is designed to be robust in the sense that if someone forgets to * TALLOC_FREE() a stackframe, then the next outer one correctly cleans up and * resets the talloc_tos(). The original motivation for this patch was to get rid of the sid_string_static & friends buffers. Explicitly passing talloc context everywhere clutters code too much for my taste, so an implicit talloc_tos() is introduced here. Many of these static buffers are replaced by a single static pointer. The intended use would thus be that low-level functions can rather freely push stuff to talloc_tos, the upper layers clean up by freeing the stackframe. The more of these stackframes are used and correctly freed the more exact the memory cleanup happens. This patch removes the main_loop_talloc_ctx, tmp_talloc_ctx and lp_talloc_ctx (did I forget any?) So, never do a tmp_ctx = talloc_init("foo"); anymore, instead, use tmp_ctx = talloc_stackframe() :-) Volker (This used to be commit 6585ea2cb7f417e14540495b9c7380fe9c8c717b) --- source3/modules/nfs4_acls.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/modules/nfs4_acls.c') diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index 200f87a559..31a9b01619 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -82,7 +82,7 @@ static SMB_ACE4_INT_T *get_validated_aceint(SMB4ACE_T *ace) SMB4ACL_T *smb_create_smb4acl(void) { - TALLOC_CTX *mem_ctx = main_loop_talloc_get(); + TALLOC_CTX *mem_ctx = talloc_tos(); SMB_ACL4_INT_T *acl = (SMB_ACL4_INT_T *)TALLOC_ZERO_SIZE(mem_ctx, sizeof(SMB_ACL4_INT_T)); if (acl==NULL) { @@ -98,7 +98,7 @@ SMB4ACL_T *smb_create_smb4acl(void) SMB4ACE_T *smb_add_ace4(SMB4ACL_T *acl, SMB_ACE4PROP_T *prop) { SMB_ACL4_INT_T *aclint = get_validated_aclint(acl); - TALLOC_CTX *mem_ctx = main_loop_talloc_get(); + TALLOC_CTX *mem_ctx = talloc_tos(); SMB_ACE4_INT_T *ace; ace = (SMB_ACE4_INT_T *)TALLOC_ZERO_SIZE(mem_ctx, sizeof(SMB_ACE4_INT_T)); @@ -267,7 +267,7 @@ size_t smb_get_nt_acl_nfs4(files_struct *fsp, size_t sd_size = 0; SEC_ACE *nt_ace_list = NULL; SEC_ACL *psa = NULL; - TALLOC_CTX *mem_ctx = main_loop_talloc_get(); + TALLOC_CTX *mem_ctx = talloc_tos(); DEBUG(10, ("smb_get_nt_acl_nfs4 invoked for %s\n", fsp->fsp_name)); @@ -529,7 +529,7 @@ static SMB4ACL_T *smbacl4_win2nfs4( { SMB4ACL_T *acl; uint32 i; - TALLOC_CTX *mem_ctx = main_loop_talloc_get(); + TALLOC_CTX *mem_ctx = talloc_tos(); DEBUG(10, ("smbacl4_win2nfs4 invoked\n")); -- cgit From 30191d1a5704ad2b158386b511558972d539ce47 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 18 Oct 2007 17:40:25 -0700 Subject: RIP BOOL. Convert BOOL -> bool. I found a few interesting bugs in various places whilst doing this (places that assumed BOOL == int). I also need to fix the Samba4 pidl generation (next checkin). Jeremy. (This used to be commit f35a266b3cbb3e5fa6a86be60f34fe340a3ca71f) --- source3/modules/nfs4_acls.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/modules/nfs4_acls.c') diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index 31a9b01619..2d81739203 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -184,7 +184,7 @@ static int smbacl4_GetFileOwner(files_struct *fsp, SMB_STRUCT_STAT *psbuf) return 0; } -static BOOL smbacl4_nfs42win(TALLOC_CTX *mem_ctx, SMB4ACL_T *acl, /* in */ +static bool smbacl4_nfs42win(TALLOC_CTX *mem_ctx, SMB4ACL_T *acl, /* in */ DOM_SID *psid_owner, /* in */ DOM_SID *psid_group, /* in */ SEC_ACE **ppnt_ace_list, /* out */ @@ -310,7 +310,7 @@ enum smbacl4_acedup_enum {e_dontcare=0, e_reject=1, e_ignore=2, e_merge=3}; typedef struct _smbacl4_vfs_params { enum smbacl4_mode_enum mode; - BOOL do_chown; + bool do_chown; enum smbacl4_acedup_enum acedup; } smbacl4_vfs_params; @@ -490,7 +490,7 @@ static int smbacl4_MergeIgnoreReject( enum smbacl4_acedup_enum acedup, SMB4ACL_T *acl, /* may modify it */ SMB_ACE4PROP_T *ace, /* the "new" ACE */ - BOOL *paddNewACE, + bool *paddNewACE, int i ) { @@ -539,7 +539,7 @@ static SMB4ACL_T *smbacl4_win2nfs4( for(i=0; inum_aces; i++) { SMB_ACE4PROP_T ace_v4; - BOOL addNewACE = True; + bool addNewACE = True; if (smbacl4_fill_ace4(mem_ctx, pparams, ownerUID, ownerGID, dacl->aces + i, &ace_v4)) @@ -565,7 +565,7 @@ NTSTATUS smb_set_nt_acl_nfs4(files_struct *fsp, { smbacl4_vfs_params params; SMB4ACL_T *acl = NULL; - BOOL result; + bool result; SMB_STRUCT_STAT sbuf; uid_t newUID = (uid_t)-1; -- cgit From 15953b82eb3b49d736b4b835b1d0d3cf0da0bff8 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 13 Oct 2007 21:06:49 +0200 Subject: Make [f]get_nt_acl return NTSTATUS (This used to be commit dcbe1bf942d017a3cd5084c6ef605a13912f795b) --- source3/modules/nfs4_acls.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'source3/modules/nfs4_acls.c') diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index 2d81739203..207c2ab537 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -257,7 +257,7 @@ static bool smbacl4_nfs42win(TALLOC_CTX *mem_ctx, SMB4ACL_T *acl, /* in */ return True; } -size_t smb_get_nt_acl_nfs4(files_struct *fsp, +NTSTATUS smb_get_nt_acl_nfs4(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc, SMB4ACL_T *acl) { @@ -272,23 +272,25 @@ size_t smb_get_nt_acl_nfs4(files_struct *fsp, DEBUG(10, ("smb_get_nt_acl_nfs4 invoked for %s\n", fsp->fsp_name)); if (acl==NULL || smb_get_naces(acl)==0) - return 0; /* special because we shouldn't alloc 0 for win */ + return NT_STATUS_ACCESS_DENIED; /* special because we + * shouldn't alloc 0 for + * win */ if (smbacl4_GetFileOwner(fsp, &sbuf)) - return 0; + return map_nt_error_from_unix(errno); uid_to_sid(&sid_owner, sbuf.st_uid); gid_to_sid(&sid_group, sbuf.st_gid); if (smbacl4_nfs42win(mem_ctx, acl, &sid_owner, &sid_group, &nt_ace_list, &good_aces)==False) { DEBUG(8,("smbacl4_nfs42win failed\n")); - return 0; + return map_nt_error_from_unix(errno); } psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, good_aces, nt_ace_list); if (psa == NULL) { DEBUG(2,("make_sec_acl failed\n")); - return 0; + return NT_STATUS_NO_MEMORY; } DEBUG(10,("after make sec_acl\n")); @@ -298,11 +300,13 @@ size_t smb_get_nt_acl_nfs4(files_struct *fsp, NULL, psa, &sd_size); if (*ppdesc==NULL) { DEBUG(2,("make_sec_desc failed\n")); - return 0; + return NT_STATUS_NO_MEMORY; } - DEBUG(10, ("smb_get_nt_acl_nfs4 successfully exited with sd_size %d\n", sd_size)); - return sd_size; + DEBUG(10, ("smb_get_nt_acl_nfs4 successfully exited with sd_size %d\n", + sec_desc_size(*ppdesc))); + + return NT_STATUS_OK; } enum smbacl4_mode_enum {e_simple=0, e_special=1}; -- cgit From 900288a2b86abd247f9eb4cd15dc5617a17cfef1 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 15 Dec 2007 21:11:36 +0100 Subject: Replace sid_string_static by sid_string_dbg in DEBUGs (This used to be commit bb35e794ec129805e874ceba882bcc1e84791a09) --- source3/modules/nfs4_acls.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'source3/modules/nfs4_acls.c') diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index 207c2ab537..edcc52261c 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -243,7 +243,7 @@ static bool smbacl4_nfs42win(TALLOC_CTX *mem_ctx, SMB4ACL_T *acl, /* in */ } } DEBUG(10, ("mapped %d to %s\n", ace->who.id, - sid_string_static(&sid))); + sid_string_dbg(&sid))); init_sec_access(&mask, ace->aceMask); init_sec_ace(&nt_ace_list[good_aces++], &sid, @@ -429,8 +429,7 @@ static int smbacl4_fill_ace4( uid_t uid; gid_t gid; - DEBUG(10, ("got ace for %s\n", - sid_string_static(&ace_nt->trustee))); + DEBUG(10, ("got ace for %s\n", sid_string_dbg(&ace_nt->trustee))); memset(ace_v4, 0, sizeof(SMB_ACE4PROP_T)); ace_v4->aceType = ace_nt->type; /* only ACCESS|DENY supported right now */ @@ -452,7 +451,7 @@ static int smbacl4_fill_ace4( } else { if (!lookup_sid(mem_ctx, &ace_nt->trustee, &dom, &name, &type)) { DEBUG(8, ("Could not find %s' type\n", - sid_string_static(&ace_nt->trustee))); + sid_string_dbg(&ace_nt->trustee))); errno = EINVAL; return -1; } @@ -460,7 +459,7 @@ static int smbacl4_fill_ace4( if (type == SID_NAME_USER) { if (!sid_to_uid(&ace_nt->trustee, &uid)) { DEBUG(2, ("Could not convert %s to uid\n", - sid_string_static(&ace_nt->trustee))); + sid_string_dbg(&ace_nt->trustee))); return -1; } @@ -473,7 +472,7 @@ static int smbacl4_fill_ace4( } else { /* else group? - TODO check it... */ if (!sid_to_gid(&ace_nt->trustee, &gid)) { DEBUG(2, ("Could not convert %s to gid\n", - sid_string_static(&ace_nt->trustee))); + sid_string_dbg(&ace_nt->trustee))); return -1; } ace_v4->aceFlags |= SMB_ACE4_IDENTIFIER_GROUP; -- cgit From cb69a78505854342013f67630bfd38a3c5cd7857 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Fri, 9 Nov 2007 01:01:55 +0100 Subject: Split smbacl4_GetFileOwner into two (f- and non-f-variant). This is in preparation of a get_nt_acl prototype change. (This used to be commit e0672a46a2e5e655da32499ca7f52a9156e9b7f0) --- source3/modules/nfs4_acls.c | 48 +++++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 19 deletions(-) (limited to 'source3/modules/nfs4_acls.c') diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index edcc52261c..94666ba00d 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -161,24 +161,35 @@ uint32 smb_get_naces(SMB4ACL_T *acl) return aclint->naces; } -static int smbacl4_GetFileOwner(files_struct *fsp, SMB_STRUCT_STAT *psbuf) +static int smbacl4_GetFileOwner(struct connection_struct *conn, + const char *filename, + SMB_STRUCT_STAT *psbuf) { memset(psbuf, 0, sizeof(SMB_STRUCT_STAT)); + + /* Get the stat struct for the owner info. */ + if (SMB_VFS_STAT(conn, filename, psbuf) != 0) + { + DEBUG(8, ("SMB_VFS_STAT failed with error %s\n", + strerror(errno))); + return -1; + } + + return 0; +} + +static int smbacl4_fGetFileOwner(files_struct *fsp, SMB_STRUCT_STAT *psbuf) +{ + memset(psbuf, 0, sizeof(SMB_STRUCT_STAT)); + if (fsp->is_directory || fsp->fh->fd == -1) { - /* Get the stat struct for the owner info. */ - if (SMB_VFS_STAT(fsp->conn,fsp->fsp_name, psbuf) != 0) - { - DEBUG(8, ("SMB_VFS_STAT failed with error %s\n", - strerror(errno))); - return -1; - } - } else { - if (SMB_VFS_FSTAT(fsp,fsp->fh->fd, psbuf) != 0) - { - DEBUG(8, ("SMB_VFS_FSTAT failed with error %s\n", - strerror(errno))); - return -1; - } + return smbacl4_GetFileOwner(fsp->conn, fsp->fsp_name, psbuf); + } + if (SMB_VFS_FSTAT(fsp,fsp->fh->fd, psbuf) != 0) + { + DEBUG(8, ("SMB_VFS_FSTAT failed with error %s\n", + strerror(errno))); + return -1; } return 0; @@ -276,9 +287,8 @@ NTSTATUS smb_get_nt_acl_nfs4(files_struct *fsp, * shouldn't alloc 0 for * win */ - if (smbacl4_GetFileOwner(fsp, &sbuf)) + if (smbacl4_fGetFileOwner(fsp, &sbuf)) return map_nt_error_from_unix(errno); - uid_to_sid(&sid_owner, sbuf.st_uid); gid_to_sid(&sid_group, sbuf.st_gid); @@ -588,7 +598,7 @@ NTSTATUS smb_set_nt_acl_nfs4(files_struct *fsp, if (smbacl4_get_vfs_params(SMBACL4_PARAM_TYPE_NAME, fsp, ¶ms)) return NT_STATUS_NO_MEMORY; - if (smbacl4_GetFileOwner(fsp, &sbuf)) + if (smbacl4_fGetFileOwner(fsp, &sbuf)) return map_nt_error_from_unix(errno); if (params.do_chown) { @@ -610,7 +620,7 @@ NTSTATUS smb_set_nt_acl_nfs4(files_struct *fsp, } DEBUG(10,("chown %s, %u, %u succeeded.\n", fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID)); - if (smbacl4_GetFileOwner(fsp, &sbuf)) + if (smbacl4_fGetFileOwner(fsp, &sbuf)) return map_nt_error_from_unix(errno); } } -- cgit From c650857fac826697cb1d9441b9ea869b85190d25 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Thu, 15 Nov 2007 00:46:20 +0100 Subject: Split smb_get_nt_acl_nfs4 into two (f- and non-f-variant). This is the next step in preparation of a get_nt_acl prototype change. Michael (This used to be commit 7afeb1c6cb1bdb58d1e61c54ae215d947d8dc3ea) --- source3/modules/nfs4_acls.c | 44 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 9 deletions(-) (limited to 'source3/modules/nfs4_acls.c') diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index 94666ba00d..70bb6a02e8 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -268,29 +268,24 @@ static bool smbacl4_nfs42win(TALLOC_CTX *mem_ctx, SMB4ACL_T *acl, /* in */ return True; } -NTSTATUS smb_get_nt_acl_nfs4(files_struct *fsp, +static NTSTATUS smb_get_nt_acl_nfs4_common(const SMB_STRUCT_STAT *sbuf, uint32 security_info, SEC_DESC **ppdesc, SMB4ACL_T *acl) { int good_aces = 0; - SMB_STRUCT_STAT sbuf; DOM_SID sid_owner, sid_group; size_t sd_size = 0; SEC_ACE *nt_ace_list = NULL; SEC_ACL *psa = NULL; TALLOC_CTX *mem_ctx = talloc_tos(); - DEBUG(10, ("smb_get_nt_acl_nfs4 invoked for %s\n", fsp->fsp_name)); - if (acl==NULL || smb_get_naces(acl)==0) return NT_STATUS_ACCESS_DENIED; /* special because we * shouldn't alloc 0 for * win */ - if (smbacl4_fGetFileOwner(fsp, &sbuf)) - return map_nt_error_from_unix(errno); - uid_to_sid(&sid_owner, sbuf.st_uid); - gid_to_sid(&sid_group, sbuf.st_gid); + uid_to_sid(&sid_owner, sbuf->st_uid); + gid_to_sid(&sid_group, sbuf->st_gid); if (smbacl4_nfs42win(mem_ctx, acl, &sid_owner, &sid_group, &nt_ace_list, &good_aces)==False) { DEBUG(8,("smbacl4_nfs42win failed\n")); @@ -313,12 +308,43 @@ NTSTATUS smb_get_nt_acl_nfs4(files_struct *fsp, return NT_STATUS_NO_MEMORY; } - DEBUG(10, ("smb_get_nt_acl_nfs4 successfully exited with sd_size %d\n", + DEBUG(10, ("smb_get_nt_acl_nfs4_common successfully exited with sd_size %d\n", sec_desc_size(*ppdesc))); return NT_STATUS_OK; } +NTSTATUS smb_fget_nt_acl_nfs4(files_struct *fsp, + uint32 security_info, + SEC_DESC **ppdesc, SMB4ACL_T *acl) +{ + SMB_STRUCT_STAT sbuf; + + DEBUG(10, ("smb_fget_nt_acl_nfs4 invoked for %s\n", fsp->fsp_name)); + + if (smbacl4_fGetFileOwner(fsp, &sbuf)) { + return map_nt_error_from_unix(errno); + } + + return smb_get_nt_acl_nfs4_common(&sbuf, security_info, ppdesc, acl); +} + +NTSTATUS smb_get_nt_acl_nfs4(struct connection_struct *conn, + const char *name, + uint32 security_info, + SEC_DESC **ppdesc, SMB4ACL_T *acl) +{ + SMB_STRUCT_STAT sbuf; + + DEBUG(10, ("smb_get_nt_acl_nfs4 invoked for %s\n", name)); + + if (smbacl4_GetFileOwner(conn, name, &sbuf)) { + return map_nt_error_from_unix(errno); + } + + return smb_get_nt_acl_nfs4_common(&sbuf, security_info, ppdesc, acl); +} + enum smbacl4_mode_enum {e_simple=0, e_special=1}; enum smbacl4_acedup_enum {e_dontcare=0, e_reject=1, e_ignore=2, e_merge=3}; -- cgit From 7cbdb48475b0340154fad60cb4b7cc53dc2bbcfd Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 29 Dec 2007 23:00:49 +0100 Subject: Remove tiny code duplication ndr_size_security_descriptor does the same as sec_desc_size (This used to be commit bc3bd7a8e7c6e9e27acb195c86abb92c0f53112f) --- source3/modules/nfs4_acls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/modules/nfs4_acls.c') diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index 70bb6a02e8..6d2972d8ed 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -309,7 +309,7 @@ static NTSTATUS smb_get_nt_acl_nfs4_common(const SMB_STRUCT_STAT *sbuf, } DEBUG(10, ("smb_get_nt_acl_nfs4_common successfully exited with sd_size %d\n", - sec_desc_size(*ppdesc))); + ndr_size_security_descriptor(*ppdesc, 0))); return NT_STATUS_OK; } -- cgit From 87a684f7fcfa8d9fabc42e33981299d0b33eeeb7 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 7 Jan 2008 13:21:26 +0100 Subject: Remove redundant parameter fd from SMB_VFS_FSTAT(). Michael (This used to be commit 0b86c420be94d295f6917a220b5d699f65b46711) --- source3/modules/nfs4_acls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/modules/nfs4_acls.c') diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index 6d2972d8ed..52d3983fff 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -185,7 +185,7 @@ static int smbacl4_fGetFileOwner(files_struct *fsp, SMB_STRUCT_STAT *psbuf) if (fsp->is_directory || fsp->fh->fd == -1) { return smbacl4_GetFileOwner(fsp->conn, fsp->fsp_name, psbuf); } - if (SMB_VFS_FSTAT(fsp,fsp->fh->fd, psbuf) != 0) + if (SMB_VFS_FSTAT(fsp, psbuf) != 0) { DEBUG(8, ("SMB_VFS_FSTAT failed with error %s\n", strerror(errno))); -- cgit From 313f7d10b884d083ef9488db739465c54c3f6515 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Wed, 16 Jan 2008 12:18:57 +0300 Subject: Merge latest fixes to vfs_gpfs and NFS4 ACLs from Samba 3.0 CTDB branch (from http://samba.org/~tridge/3_0-ctdb) Signed-off-by: Alexander Bokovoy (This used to be commit 1daad835cbfb4615a8fe7a241f4d578f7e69f214) --- source3/modules/nfs4_acls.c | 187 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 151 insertions(+), 36 deletions(-) (limited to 'source3/modules/nfs4_acls.c') diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index 52d3983fff..0c3d010dcd 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -20,6 +20,9 @@ #include "includes.h" #include "nfs4_acls.h" +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_ACLS + #define SMBACL4_PARAM_TYPE_NAME "nfs4" #define SMB_ACE4_INT_MAGIC 0x76F8A967 @@ -352,6 +355,7 @@ typedef struct _smbacl4_vfs_params { enum smbacl4_mode_enum mode; bool do_chown; enum smbacl4_acedup_enum acedup; + struct db_context *sid_mapping_table; } smbacl4_vfs_params; /* @@ -451,8 +455,65 @@ static SMB_ACE4PROP_T *smbacl4_find_equal_special( return NULL; } -static int smbacl4_fill_ace4( +static bool nfs4_map_sid(smbacl4_vfs_params *params, const DOM_SID *src, + DOM_SID *dst) +{ + static struct db_context *mapping_db = NULL; + TDB_DATA data; + + if (mapping_db == NULL) { + const char *dbname = lp_parm_const_string( + -1, SMBACL4_PARAM_TYPE_NAME, "sidmap", NULL); + + if (dbname == NULL) { + DEBUG(10, ("%s:sidmap not defined\n", + SMBACL4_PARAM_TYPE_NAME)); + return False; + } + + become_root(); + mapping_db = db_open(NULL, dbname, 0, TDB_DEFAULT, + O_RDONLY, 0600); + unbecome_root(); + + if (mapping_db == NULL) { + DEBUG(1, ("could not open sidmap: %s\n", + strerror(errno))); + return False; + } + } + + if (mapping_db->fetch(mapping_db, NULL, + string_term_tdb_data(sid_string_tos(src)), + &data) == -1) { + DEBUG(10, ("could not find mapping for SID %s\n", + sid_string_dbg(src))); + return False; + } + + if ((data.dptr == NULL) || (data.dsize <= 0) + || (data.dptr[data.dsize-1] != '\0')) { + DEBUG(5, ("invalid mapping for SID %s\n", + sid_string_dbg(src))); + TALLOC_FREE(data.dptr); + return False; + } + + if (!string_to_sid(dst, (char *)data.dptr)) { + DEBUG(1, ("invalid mapping %s for SID %s\n", + (char *)data.dptr, sid_string_dbg(src))); + TALLOC_FREE(data.dptr); + return False; + } + + TALLOC_FREE(data.dptr); + + return True; +} + +static bool smbacl4_fill_ace4( TALLOC_CTX *mem_ctx, + const char *filename, smbacl4_vfs_params *params, uid_t ownerUID, gid_t ownerGID, @@ -460,11 +521,6 @@ static int smbacl4_fill_ace4( SMB_ACE4PROP_T *ace_v4 /* output */ ) { - const char *dom, *name; - enum lsa_SidType type; - uid_t uid; - gid_t gid; - DEBUG(10, ("got ace for %s\n", sid_string_dbg(&ace_nt->trustee))); memset(ace_v4, 0, sizeof(SMB_ACE4PROP_T)); @@ -485,18 +541,46 @@ static int smbacl4_fill_ace4( ace_v4->who.special_id = SMB_ACE4_WHO_EVERYONE; ace_v4->flags |= SMB_ACE4_ID_SPECIAL; } else { - if (!lookup_sid(mem_ctx, &ace_nt->trustee, &dom, &name, &type)) { - DEBUG(8, ("Could not find %s' type\n", - sid_string_dbg(&ace_nt->trustee))); - errno = EINVAL; - return -1; + const char *dom, *name; + enum lsa_SidType type; + uid_t uid; + gid_t gid; + DOM_SID sid; + + sid_copy(&sid, &ace_nt->trustee); + + if (!lookup_sid(mem_ctx, &sid, &dom, &name, &type)) { + + DOM_SID mapped; + + if (!nfs4_map_sid(params, &sid, &mapped)) { + DEBUG(1, ("nfs4_acls.c: file [%s]: SID %s " + "unknown\n", filename, sid_string_dbg(&sid))); + errno = EINVAL; + return False; + } + + DEBUG(2, ("nfs4_acls.c: file [%s]: mapped SID %s " + "to %s\n", filename, sid_string_dbg(&sid), sid_string_dbg(&mapped))); + + if (!lookup_sid(mem_ctx, &mapped, &dom, + &name, &type)) { + DEBUG(1, ("nfs4_acls.c: file [%s]: SID %s " + "mapped from %s is unknown\n", + filename, sid_string_dbg(&mapped), sid_string_dbg(&sid))); + errno = EINVAL; + return False; + } + + sid_copy(&sid, &mapped); } - + if (type == SID_NAME_USER) { - if (!sid_to_uid(&ace_nt->trustee, &uid)) { - DEBUG(2, ("Could not convert %s to uid\n", - sid_string_dbg(&ace_nt->trustee))); - return -1; + if (!sid_to_uid(&sid, &uid)) { + DEBUG(1, ("nfs4_acls.c: file [%s]: could not " + "convert %s to uid\n", filename, + sid_string_dbg(&sid))); + return False; } if (params->mode==e_special && uid==ownerUID) { @@ -506,11 +590,13 @@ static int smbacl4_fill_ace4( ace_v4->who.uid = uid; } } else { /* else group? - TODO check it... */ - if (!sid_to_gid(&ace_nt->trustee, &gid)) { - DEBUG(2, ("Could not convert %s to gid\n", - sid_string_dbg(&ace_nt->trustee))); - return -1; + if (!sid_to_gid(&sid, &gid)) { + DEBUG(1, ("nfs4_acls.c: file [%s]: could not " + "convert %s to gid\n", filename, + sid_string_dbg(&sid))); + return False; } + ace_v4->aceFlags |= SMB_ACE4_IDENTIFIER_GROUP; if (params->mode==e_special && gid==ownerGID) { @@ -522,7 +608,7 @@ static int smbacl4_fill_ace4( } } - return 0; /* OK */ + return True; /* OK */ } static int smbacl4_MergeIgnoreReject( @@ -560,6 +646,7 @@ static int smbacl4_MergeIgnoreReject( } static SMB4ACL_T *smbacl4_win2nfs4( + const char *filename, SEC_ACL *dacl, smbacl4_vfs_params *pparams, uid_t ownerUID, @@ -580,9 +667,14 @@ static SMB4ACL_T *smbacl4_win2nfs4( SMB_ACE4PROP_T ace_v4; bool addNewACE = True; - if (smbacl4_fill_ace4(mem_ctx, pparams, ownerUID, ownerGID, - dacl->aces + i, &ace_v4)) - return NULL; + if (!smbacl4_fill_ace4(mem_ctx, filename, pparams, + ownerUID, ownerGID, + dacl->aces + i, &ace_v4)) { + DEBUG(3, ("Could not fill ace for file %s, SID %s\n", + filename, + sid_string_dbg(&((dacl->aces+i)->trustee)))); + continue; + } if (pparams->acedup!=e_dontcare) { if (smbacl4_MergeIgnoreReject(pparams->acedup, acl, @@ -607,6 +699,7 @@ NTSTATUS smb_set_nt_acl_nfs4(files_struct *fsp, bool result; SMB_STRUCT_STAT sbuf; + bool need_chown = False; uid_t newUID = (uid_t)-1; gid_t newGID = (gid_t)-1; @@ -635,25 +728,33 @@ NTSTATUS smb_set_nt_acl_nfs4(files_struct *fsp, return status; } if (((newUID != (uid_t)-1) && (sbuf.st_uid != newUID)) || - ((newGID != (gid_t)-1) && (sbuf.st_gid != newGID))) { - if(try_chown(fsp->conn, fsp->fsp_name, newUID, newGID)) { - DEBUG(3,("chown %s, %u, %u failed. Error = %s.\n", - fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID, strerror(errno) )); - if (errno == EPERM) { - return NT_STATUS_INVALID_OWNER; + ((newGID != (gid_t)-1) && (sbuf.st_gid != newGID))) { + need_chown = True; + } + if (need_chown) { + if ((newUID == (uid_t)-1 || newUID == current_user.ut.uid)) { + if(try_chown(fsp->conn, fsp->fsp_name, newUID, newGID)) { + DEBUG(3,("chown %s, %u, %u failed. Error = %s.\n", + fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID, + strerror(errno))); + return map_nt_error_from_unix(errno); } - return map_nt_error_from_unix(errno); + + DEBUG(10,("chown %s, %u, %u succeeded.\n", + fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID)); + if (smbacl4_GetFileOwner(fsp->conn, fsp->fsp_name, &sbuf)) + return map_nt_error_from_unix(errno); + need_chown = False; + } else { /* chown is needed, but _after_ changing acl */ + sbuf.st_uid = newUID; /* OWNER@ in case of e_special */ + sbuf.st_gid = newGID; /* GROUP@ in case of e_special */ } - DEBUG(10,("chown %s, %u, %u succeeded.\n", - fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID)); - if (smbacl4_fGetFileOwner(fsp, &sbuf)) - return map_nt_error_from_unix(errno); } } if ((security_info_sent & DACL_SECURITY_INFORMATION)!=0 && psd->dacl!=NULL) { - acl = smbacl4_win2nfs4(psd->dacl, ¶ms, sbuf.st_uid, sbuf.st_gid); + acl = smbacl4_win2nfs4(fsp->fsp_name, psd->dacl, ¶ms, sbuf.st_uid, sbuf.st_gid); if (!acl) return map_nt_error_from_unix(errno); @@ -668,6 +769,20 @@ NTSTATUS smb_set_nt_acl_nfs4(files_struct *fsp, } else DEBUG(10, ("no dacl found; security_info_sent = 0x%x\n", security_info_sent)); + /* Any chown pending? */ + if (need_chown) { + DEBUG(3,("chown#2 %s. uid = %u, gid = %u.\n", + fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID)); + if (try_chown(fsp->conn, fsp->fsp_name, newUID, newGID)) { + DEBUG(2,("chown#2 %s, %u, %u failed. Error = %s.\n", + fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID, + strerror(errno))); + return map_nt_error_from_unix(errno); + } + DEBUG(10,("chown#2 %s, %u, %u succeeded.\n", + fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID)); + } + DEBUG(10, ("smb_set_nt_acl_nfs4 succeeded\n")); return NT_STATUS_OK; } -- cgit From e1732fae331dd15a0a05c309baa6f7fd02f220e4 Mon Sep 17 00:00:00 2001 From: Michael Adam Date: Mon, 16 Jun 2008 23:50:17 +0200 Subject: Remove reference to current_user from modules/nfs4_acls.c . Michael (This used to be commit 50fbfa03483de0059d85967dc96f2896e55e6d04) --- source3/modules/nfs4_acls.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/modules/nfs4_acls.c') diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index 0c3d010dcd..927163d7b0 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -42,7 +42,6 @@ typedef struct _SMB_ACL4_INT_T SMB_ACE4_INT_T *last; } SMB_ACL4_INT_T; -extern struct current_user current_user; extern int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid); extern NTSTATUS unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, SEC_DESC *psd); @@ -732,7 +731,7 @@ NTSTATUS smb_set_nt_acl_nfs4(files_struct *fsp, need_chown = True; } if (need_chown) { - if ((newUID == (uid_t)-1 || newUID == current_user.ut.uid)) { + if ((newUID == (uid_t)-1 || newUID == fsp->conn->server_info->uid)) { if(try_chown(fsp->conn, fsp->fsp_name, newUID, newGID)) { DEBUG(3,("chown %s, %u, %u failed. Error = %s.\n", fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID, -- cgit From e9489e9ff6c34c86eb3e2cc4b371eec4c6342ac3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 11 Jul 2008 13:03:42 +0200 Subject: Fix the build of nfs4_acls.c (This used to be commit 2abb7cd867be307e56c02087e700189b17efb894) --- source3/modules/nfs4_acls.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/modules/nfs4_acls.c') diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index 927163d7b0..dc1b70ccb7 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -731,7 +731,8 @@ NTSTATUS smb_set_nt_acl_nfs4(files_struct *fsp, need_chown = True; } if (need_chown) { - if ((newUID == (uid_t)-1 || newUID == fsp->conn->server_info->uid)) { + if ((newUID == (uid_t)-1 + || newUID == fsp->conn->server_info->utok.uid)) { if(try_chown(fsp->conn, fsp->fsp_name, newUID, newGID)) { DEBUG(3,("chown %s, %u, %u failed. Error = %s.\n", fsp->fsp_name, (unsigned int)newUID, (unsigned int)newGID, -- cgit From d4b41079cb6bfffa75e3d7b188ab4331f7aa32b8 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 8 Sep 2008 16:42:06 +0200 Subject: When setting an NFSv4 ACL, map generic bits (This used to be commit dbe7a61be2beac50d1665e38ac374cefbbabec00) --- source3/modules/nfs4_acls.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/modules/nfs4_acls.c') diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index dc1b70ccb7..9e28db8b39 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -25,6 +25,8 @@ #define SMBACL4_PARAM_TYPE_NAME "nfs4" +extern const struct generic_mapping file_generic_mapping; + #define SMB_ACE4_INT_MAGIC 0x76F8A967 typedef struct _SMB_ACE4_INT_T { @@ -528,6 +530,8 @@ static bool smbacl4_fill_ace4( ace_v4->aceMask = ace_nt->access_mask & (STD_RIGHT_ALL_ACCESS | SA_RIGHT_FILE_ALL_ACCESS); + se_map_generic(&ace_v4->aceMask, &file_generic_mapping); + if (ace_v4->aceFlags!=ace_nt->flags) DEBUG(9, ("ace_v4->aceFlags(0x%x)!=ace_nt->flags(0x%x)\n", ace_v4->aceFlags, ace_nt->flags)); -- cgit