1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-11 05:18:09 +03:00

r18603: Add in the NFSv4 ACL mapping code from IBM.

Sorry for the delay :-).
Jeremy.
This commit is contained in:
Jeremy Allison 2006-09-18 02:27:48 +00:00 committed by Gerald (Jerry) Carter
parent 2ab0ab3262
commit a52fa21895
8 changed files with 1443 additions and 3 deletions

View File

@ -406,6 +406,7 @@ VFS_SHADOW_COPY_OBJ = modules/vfs_shadow_copy.o
VFS_AFSACL_OBJ = modules/vfs_afsacl.o
VFS_POSIXACL_OBJ = modules/vfs_posixacl.o
VFS_AIXACL_OBJ = modules/vfs_aixacl.o modules/vfs_aixacl_util.o
VFS_AIXACL2_OBJ = modules/vfs_aixacl2.o modules/vfs_aixacl_util.o modules/nfs4_acls.o
VFS_SOLARISACL_OBJ = modules/vfs_solarisacl.o
VFS_HPUXACL_OBJ = modules/vfs_hpuxacl.o
VFS_IRIXACL_OBJ = modules/vfs_irixacl.o
@ -1426,6 +1427,11 @@ bin/aixacl.@SHLIBEXT@: $(VFS_AIXACL_OBJ:.o=.@PICSUFFIX@)
@$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_AIXACL_OBJ:.o=.@PICSUFFIX@) \
@SONAMEFLAG@`basename $@`
bin/aixacl2.@SHLIBEXT@: $(VFS_AIXACL2_OBJ:.o=.@PICSUFFIX@)
@echo "Building plugin $@"
@$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_AIXACL2_OBJ:.o=.@PICSUFFIX@) \
@SONAMEFLAG@`basename $@`
bin/solarisacl.@SHLIBEXT@: $(VFS_SOLARISACL_OBJ:.o=.@PICSUFFIX@)
@echo "Building plugin $@"
@$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_SOLARISACL_OBJ:.o=.@PICSUFFIX@) \

View File

@ -5726,6 +5726,7 @@ SMB_MODULE(vfs_shadow_copy, \$(VFS_SHADOW_COPY_OBJ), "bin/shadow_copy.$SHLIBEXT"
SMB_MODULE(vfs_afsacl, \$(VFS_AFSACL_OBJ), "bin/afsacl.$SHLIBEXT", VFS)
SMB_MODULE(vfs_posixacl, \$(VFS_POSIXACL_OBJ), "bin/posixacl.$SHLIBEXT", VFS)
SMB_MODULE(vfs_aixacl, \$(VFS_AIXACL_OBJ), "bin/aixacl.$SHLIBEXT", VFS)
SMB_MODULE(vfs_aixacl2, \$(VFS_AIXACL2_OBJ), "bin/aixacl2.$SHLIBEXT", VFS)
SMB_MODULE(vfs_solarisacl, \$(VFS_SOLARISACL_OBJ), "bin/solarisacl.$SHLIBEXT", VFS)
SMB_MODULE(vfs_irixacl, \$(VFS_IRIXACL_OBJ), "bin/irixacl.$SHLIBEXT", VFS)
SMB_MODULE(vfs_hpuxacl, \$(VFS_HPUXACL_OBJ), "bin/hpuxacl.$SHLIBEXT", VFS)

View File

@ -0,0 +1,82 @@
Configuring NFS4 ACLs in Samba3
===============================
Created: Peter Somogyi, 2006-JUN-06
Last modified: Peter Somogyi, 2006-JUL-20
Revision no.: 4
-------------------------------
Parameters in smb.conf:
=======================
Each parameter must have a prefix "nfs4:".
Each one affects the behaviour only when _setting_ an acl on a file/dir:
mode = [simple|special]
- simple: don't use OWNER@ and GROUP@ special IDs in ACEs. - default
- special: use OWNER@ and GROUP@ special IDs in ACEs instead of simple user&group ids.
Note: EVERYONE@ is always processed (if found such an ACE).
Note2: special mode will have side effect when _only_ chown is performed. Later this may be worked out.
Use "simple" mode when the share is used mainly by windows users and unix side is not significant. You will loose unix bits in this case.
It's strongly advised setting "store dos attributes = yes" in smb.conf.
chown = [true|false]
- true => enable changing owner and group - default.
- false => disable support for changing owner or group
acedup = [dontcare|reject|ignore|merge]
- dontcare: copy ACEs as they come, don't care with "duplicate" records. Default.
- reject: stop operation, exit acl setter operation with an error
- ignore: don't include the second matching ACE
- merge: OR 2 ace.flag fields and 2 ace.mask fields of the 2 duplicate ACEs into 1 ACE
Two ACEs are considered here "duplicate" when their type and id fields are matching.
Example:
[smbtest]
path = /tests/psomogyi/smbtest
writable = yes
vfs objects = aixacl2
nfs4: mode = special
nfs4: chown = yes
nfs4: acedup = merge
Configuring AIX ACL support
==============================
Binaries: (default install path is [samba]/lib/vfs/)
- aixacl.so: provides AIXC ACL support only, can be compiled and works on all AIX platforms
- aixacl2.so: provides AIXC and JFS2-NFS4 ACL support, can be compiled and works only under AIX 5.3 and newer.
NFS4 acl currently has support only under JFS2 (ext. attr. format must be set to v2).
aixacl2.so always detects support for NFS4 acls and redirects to POSIX ACL handling automatically when NFS4 is not supported for a path.
Adding "vfs objects = aixacl2" to a share should be done only in case when NFS4 is really supported by the filesystem.
(Otherwise you may get performance loss.)
For configuration see also the example above.
General notes
=============
NFS4 handling logic is separated from AIX/jfs2 ACL parsing.
Samba and its VFS modules dosn't reorder ACEs. Windows clients do that (and the smbcacl tool). MSDN also says deny ACEs must come first.
NFS4 ACL's validity is checked by the system API, not by Samba.
NFS4 ACL rights are enforced by the OS or filesystem, not by Samba.
The flag INHERITED_ACE is never set (not required, as doesn't do WinNT/98/me, only since Win2k).
Win2k GUI behaves strangely when detecting inheritance (sometimes it doesn't detect,
but after adding an ace it shows that - it's some GUI error).
Unknown (unmappable) SIDs are not accepted.
TODOs
=====
- Creator Owner & Group SID handling (same way as posix)
- the 4 generic rights bits support (GENERIC_RIGHT_READ_ACCESS, WRITE, EXEC, ALL)
- chown & no ACL, but we have ONWER@ and GROUP@
- DIALUP, ANONYMOUS, ... builtin SIDs
- audit & alarm support - in theory it's forwarded so it should work, but currently there's no platform which supports them to test
- support for a real NFS4 client (we don't have an accepted API yet)

668
source/modules/nfs4_acls.c Normal file
View File

@ -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; i<dacl->num_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, &params))
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, &params, 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;
}

146
source/modules/nfs4_acls.h Normal file
View File

@ -0,0 +1,146 @@
/*
* NFS4 ACL handling
*
* Copyright (C) Jim McDonough, 2006
* Reused & renamed some parts of AIX 5.3 sys/acl.h structures
*
* 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.
*/
#ifndef __NFS4_ACLS_H__
#define __NFS4_ACLS_H__
#define SMB_ACLTYPE_NONE 0
#define SMB_ACLTYPE_UNKNOWN 1
#define SMB_ACLTYPE_POSIX 2
#define SMB_ACLTYPE_NFS4 4
/*
* Following union captures the identity as
* used in the NFS4 ACL structures.
*/
typedef union _SMB_NFS4_ACEWHOID_T {
uid_t uid; /* User id */
gid_t gid; /* Group id */
uint32 special_id; /* Identifies special identities in NFS4 */
#define SMB_ACE4_WHO_OWNER 0x00000001 /*The owner of the file. */
#define SMB_ACE4_WHO_GROUP 0x00000002 /*The group associated with the file. */
#define SMB_ACE4_WHO_EVERYONE 0x00000003 /*The world. */
#define SMB_ACE4_WHO_INTERACTIVE 0x00000004 /*Accessed from an interactive terminal. */
#define SMB_ACE4_WHO_NETWORK 0x00000005 /*Accessed via the network. */
#define SMB_ACE4_WHO_DIALUP 0x00000006 /*Accessed as a dialup user to the server. */
#define SMB_ACE4_WHO_BATCH 0x00000007 /*Accessed from a batch job. */
#define SMB_ACE4_WHO_ANONYMOUS 0x00000008 /*Accessed without any authentication. */
#define SMB_ACE4_WHO_AUTHENTICATED 0x00000009 /*Any authenticated user (opposite of ANONYMOUS) */
#define SMB_ACE4_WHO_SERVICE 0x0000000A /*Access from a system service. */
#define SMB_ACE4_WHO_MAX SMB_ACE4_WHO_SERVICE /* largest valid ACE4_WHO */
uint32 id;
} SMB_NFS4_ACEWHOID_T;
typedef struct _SMB_ACE4PROP_T {
uint32 flags; /* Bit mask defining details of ACE */
/*The following are constants for flags field */
/* #define SMB_ACE4_ID_NOT_VALID 0x00000001 - from aix/jfs2 */
#define SMB_ACE4_ID_SPECIAL 0x00000002
SMB_NFS4_ACEWHOID_T who; /* Identifies to whom this ACE applies */
/* The following part of ACE has the same layout as NFSv4 wire format. */
uint32 aceType; /* Type of ACE PERMIT/ALLOW etc*/
/*The constants used for the type field (acetype4) are as follows: */
#define SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE 0x00000000
#define SMB_ACE4_ACCESS_DENIED_ACE_TYPE 0x00000001
#define SMB_ACE4_SYSTEM_AUDIT_ACE_TYPE 0x00000002
#define SMB_ACE4_SYSTEM_ALARM_ACE_TYPE 0x00000003
#define SMB_ACE4_MAX_TYPE ACE4_SYSTEM_ALARM_ACE_TYPE /* largest valid ACE4_TYPE */
uint32 aceFlags; /* Controls Inheritance and such */
/*The bitmask constants used for the flag field are as follows: */
#define SMB_ACE4_FILE_INHERIT_ACE 0x00000001
#define SMB_ACE4_DIRECTORY_INHERIT_ACE 0x00000002
#define SMB_ACE4_NO_PROPAGATE_INHERIT_ACE 0x00000004
#define SMB_ACE4_INHERIT_ONLY_ACE 0x00000008
#define SMB_ACE4_SUCCESSFUL_ACCESS_ACE_FLAG 0x00000010
#define SMB_ACE4_FAILED_ACCESS_ACE_FLAG 0x00000020
#define SMB_ACE4_IDENTIFIER_GROUP 0x00000040
#define SMB_ACE4_ALL_FLAGS ( SMB_ACE4_FILE_INHERIT_ACE | SMB_ACE4_DIRECTORY_INHERIT_ACE \
| SMB_ACE4_NO_PROPAGATE_INHERIT_ACE | SMB_ACE4_INHERIT_ONLY_ACE | SMB_ACE4_SUCCESSFUL_ACCESS_ACE_FLAG \
| SMB_ACE4_FAILED_ACCESS_ACE_FLAG | SMB_ACE4_IDENTIFIER_GROUP )
uint32 aceMask; /* Access rights */
/*The bitmask constants used for the access mask field are as follows: */
#define SMB_ACE4_READ_DATA 0x00000001
#define SMB_ACE4_LIST_DIRECTORY 0x00000001
#define SMB_ACE4_WRITE_DATA 0x00000002
#define SMB_ACE4_ADD_FILE 0x00000002
#define SMB_ACE4_APPEND_DATA 0x00000004
#define SMB_ACE4_ADD_SUBDIRECTORY 0x00000004
#define SMB_ACE4_READ_NAMED_ATTRS 0x00000008
#define SMB_ACE4_WRITE_NAMED_ATTRS 0x00000010
#define SMB_ACE4_EXECUTE 0x00000020
#define SMB_ACE4_DELETE_CHILD 0x00000040
#define SMB_ACE4_READ_ATTRIBUTES 0x00000080
#define SMB_ACE4_WRITE_ATTRIBUTES 0x00000100
#define SMB_ACE4_DELETE 0x00010000
#define SMB_ACE4_READ_ACL 0x00020000
#define SMB_ACE4_WRITE_ACL 0x00040000
#define SMB_ACE4_WRITE_OWNER 0x00080000
#define SMB_ACE4_SYNCHRONIZE 0x00100000
#define SMB_ACE4_ALL_MASKS ( SMB_ACE4_READ_DATA | SMB_ACE4_LIST_DIRECTORY \
| SMB_ACE4_WRITE_DATA | SMB_ACE4_ADD_FILE | SMB_ACE4_APPEND_DATA | SMB_ACE4_ADD_SUBDIRECTORY \
| SMB_ACE4_READ_NAMED_ATTRS | SMB_ACE4_WRITE_NAMED_ATTRS | SMB_ACE4_EXECUTE | SMB_ACE4_DELETE_CHILD \
| SMB_ACE4_READ_ATTRIBUTES | SMB_ACE4_WRITE_ATTRIBUTES | SMB_ACE4_DELETE | SMB_ACE4_READ_ACL \
| SMB_ACE4_WRITE_ACL | SMB_ACE4_WRITE_OWNER | SMB_ACE4_SYNCHRONIZE )
} SMB_ACE4PROP_T;
/*
* Never allocate these structures on your own
* use create_smb4acl instead
*/
typedef struct _SMB4ACL_T {char dontuse;} SMB4ACL_T;
typedef struct _SMB4ACE_T {char dontuse;} SMB4ACE_T;
SMB4ACL_T *smb_create_smb4acl(void);
/* prop's contents are copied */
/* it doesn't change the order, appends */
SMB4ACE_T *smb_add_ace4(SMB4ACL_T *acl, SMB_ACE4PROP_T *prop);
SMB_ACE4PROP_T *smb_get_ace4(SMB4ACE_T *ace);
/* Returns NULL if none - or error */
SMB4ACE_T *smb_first_ace4(SMB4ACL_T *acl);
/* Returns NULL in the end - or error */
SMB4ACE_T *smb_next_ace4(SMB4ACE_T *ace);
uint32 smb_get_naces(SMB4ACL_T *acl);
size_t smb_get_nt_acl_nfs4(files_struct *fsp,
uint32 security_info,
SEC_DESC **ppdesc, SMB4ACL_T *acl);
/* Callback function needed to set the native acl
* when applicable */
typedef BOOL (*set_nfs4acl_native_fn_t)(files_struct *, SMB4ACL_T *);
BOOL smb_set_nt_acl_nfs4(files_struct *fsp,
uint32 security_info_sent,
SEC_DESC *psd,
set_nfs4acl_native_fn_t set_nfs4_native);
#endif /* __NFS4_ACLS_H__ */

View File

@ -0,0 +1,537 @@
/*
* Convert JFS2 NFS4/AIXC acls to NT acls and vice versa.
*
* Copyright (C) Volker Lendecke, 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.c"
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_VFS
#define AIXACL2_MODULE_NAME "aixacl2"
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);
extern SMB_ACL_T aixacl_to_smbacl( struct acl *file_acl);
extern struct acl *aixacl_smb_to_aixacl(SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl);
typedef union aixjfs2_acl_t {
nfs4_acl_int_t jfs2_acl[1];
aixc_acl_t aixc_acl[1];
}AIXJFS2_ACL_T;
static int32_t aixacl2_getlen(AIXJFS2_ACL_T *acl, acl_type_t *type)
{
int32_t len;
if(type->u64 == ACL_NFS4) {
len = acl->jfs2_acl[0].aclLength;
}
else {
if(type->u64 == ACL_AIXC) {
len = acl->aixc_acl[0].acl_len;
} else {
DEBUG(0,("aixacl2_getlen:unknown type:%d\n",type->u64));
return False;
}
}
DEBUG(10,("aixacl2_getlen:%d\n",len));
return len;
}
static AIXJFS2_ACL_T *aixjfs2_getacl_alloc(const char *fname, acl_type_t *type)
{
AIXJFS2_ACL_T *acl;
size_t len = 200;
mode_t mode;
int ret;
uint64_t ctl_flag=0;
TALLOC_CTX *mem_ctx;
mem_ctx = main_loop_talloc_get();
acl = (AIXJFS2_ACL_T *)talloc_size(mem_ctx, len);
if (acl == NULL) {
errno = ENOMEM;
return NULL;
}
if(type->u64 == ACL_ANY) {
ctl_flag = ctl_flag | GET_ACLINFO_ONLY;
}
ret = aclx_get((char *)fname, ctl_flag, type, acl, &len, &mode);
if ((ret != 0) && (errno == ENOSPC)) {
len = aixacl2_getlen(acl, type) + sizeof(AIXJFS2_ACL_T);
DEBUG(10,("aixjfs2_getacl_alloc - acl_len:%d\n",len));
acl = (AIXJFS2_ACL_T *)talloc_size(mem_ctx, len);
if (acl == NULL) {
errno = ENOMEM;
return NULL;
}
ret = aclx_get((char *)fname, ctl_flag, type, acl, &len, &mode);
}
if (ret != 0) {
DEBUG(8, ("aclx_get failed with %s\n", strerror(errno)));
return NULL;
}
return acl;
}
static BOOL aixjfs2_get_nfs4_acl(files_struct *fsp,
SMB4ACL_T **ppacl, BOOL *pretryPosix)
{
int32_t i;
AIXJFS2_ACL_T *pacl = NULL;
nfs4_acl_int_t *jfs2_acl = NULL;
nfs4_ace_int_t *jfs2_ace = NULL;
acl_type_t type;
DEBUG(10,("jfs2 get_nt_acl invoked for %s\n", fsp->fsp_name));
memset(&type, 0, sizeof(acl_type_t));
type.u64 = ACL_NFS4;
pacl = aixjfs2_getacl_alloc(fsp->fsp_name, &type);
if (pacl == NULL) {
DEBUG(9, ("aixjfs2_getacl_alloc failed for %s with %s\n",
fsp->fsp_name, strerror(errno)));
if (errno==ENOSYS)
*pretryPosix = True;
return False;
}
jfs2_acl = &pacl->jfs2_acl[0];
DEBUG(10, ("len: %d, version: %d, nace: %d, type: 0x%x\n",
jfs2_acl->aclLength, jfs2_acl->aclVersion, jfs2_acl->aclEntryN, type.u64));
*ppacl = smb_create_smb4acl();
if (*ppacl==NULL)
return False;
jfs2_ace = &jfs2_acl->aclEntry[0];
for (i=0; i<jfs2_acl->aclEntryN; i++) {
SMB_ACE4PROP_T aceprop;
DEBUG(10, ("type: %d, iflags: %x, flags: %x, mask: %x, "
"who: %d, aclLen: %d\n", jfs2_ace->aceType, jfs2_ace->flags,
jfs2_ace->aceFlags, jfs2_ace->aceMask, jfs2_ace->aceWho.id, jfs2_ace->entryLen));
aceprop.aceType = jfs2_ace->aceType;
aceprop.aceFlags = jfs2_ace->aceFlags;
aceprop.aceMask = jfs2_ace->aceMask;
aceprop.flags = (jfs2_ace->flags&ACE4_ID_SPECIAL) ? SMB_ACE4_ID_SPECIAL : 0;
/* don't care it's real content is only 16 or 32 bit */
aceprop.who.id = jfs2_ace->aceWho.id;
if (smb_add_ace4(*ppacl, &aceprop)==NULL)
return False;
/* iterate to the next jfs2 ace */
jfs2_ace = (nfs4_ace_int_t *)(((char *)jfs2_ace) + jfs2_ace->entryLen);
}
DEBUG(10,("jfs2 get_nt_acl finished successfully\n"));
return True;
}
static size_t aixjfs2_get_nt_acl_common(files_struct *fsp,
uint32 security_info, SEC_DESC **ppdesc)
{
SMB4ACL_T *pacl = NULL;
BOOL result;
BOOL retryPosix = False;
*ppdesc = NULL;
result = aixjfs2_get_nfs4_acl(fsp, &pacl, &retryPosix);
if (retryPosix)
{
DEBUG(10, ("retrying with posix acl...\n"));
return get_nt_acl(fsp, security_info, ppdesc);
}
if (result==False)
return 0;
return smb_get_nt_acl_nfs4(fsp, security_info, ppdesc, pacl);
}
size_t aixjfs2_fget_nt_acl(vfs_handle_struct *handle,
files_struct *fsp, int fd, uint32 security_info,
SEC_DESC **ppdesc)
{
return aixjfs2_get_nt_acl_common(fsp, security_info, ppdesc);
}
size_t aixjfs2_get_nt_acl(vfs_handle_struct *handle,
files_struct *fsp, const char *name,
uint32 security_info, SEC_DESC **ppdesc)
{
return aixjfs2_get_nt_acl_common(fsp, security_info, ppdesc);
}
static SMB_ACL_T aixjfs2_get_posix_acl(const char *path, acl_type_t type)
{
aixc_acl_t *pacl;
AIXJFS2_ACL_T *acl;
SMB_ACL_T result = NULL;
int ret;
acl = aixjfs2_getacl_alloc(path, &type);
if (acl == NULL) {
DEBUG(10, ("aixjfs2_getacl failed for %s with %s\n",
path, strerror(errno)));
if (errno == 0) {
errno = EINVAL;
}
goto done;
}
pacl = &acl->aixc_acl[0];
DEBUG(10, ("len: %d, mode: %d\n",
pacl->acl_len, pacl->acl_mode));
result = aixacl_to_smbacl(pacl);
if (result == NULL) {
goto done;
}
done:
if (errno != 0) {
SAFE_FREE(result);
}
return result;
}
SMB_ACL_T aixjfs2_sys_acl_get_file(vfs_handle_struct *handle,
const char *path_p,
SMB_ACL_TYPE_T type)
{
acl_type_t aixjfs2_type;
switch(type) {
case SMB_ACL_TYPE_ACCESS:
aixjfs2_type.u64 = ACL_AIXC;
break;
case SMB_ACL_TYPE_DEFAULT:
DEBUG(0, ("Got AIX JFS2 unsupported type: %d\n", type));
return NULL;
default:
DEBUG(0, ("Got invalid type: %d\n", type));
smb_panic("exiting");
}
return aixjfs2_get_posix_acl(path_p, aixjfs2_type);
}
SMB_ACL_T aixjfs2_sys_acl_get_fd(vfs_handle_struct *handle,
files_struct *fsp,
int fd)
{
acl_type_t aixjfs2_type;
aixjfs2_type.u64 = ACL_AIXC;
return aixjfs2_get_posix_acl(fsp->fsp_name, aixjfs2_type);
}
/*
* Test whether we have that aclType support on the given path
*/
static int aixjfs2_query_acl_support(
char *filepath,
uint64_t aclType,
acl_type_t *pacl_type_info
)
{
acl_types_list_t acl_type_list;
size_t acl_type_list_len = sizeof(acl_types_list_t);
uint32_t i;
memset(&acl_type_list, 0, sizeof(acl_type_list));
if (aclx_gettypes(filepath, &acl_type_list, &acl_type_list_len)) {
DEBUG(2, ("aclx_gettypes failed with error %s for %s\n",
strerror(errno), filepath));
return -1;
}
for(i=0; i<acl_type_list.num_entries; i++) {
if (acl_type_list.entries[i].u64==aclType) {
memcpy(pacl_type_info, acl_type_list.entries + i, sizeof(acl_type_t));
DEBUG(10, ("found %s ACL support for %s\n",
pacl_type_info->acl_type, filepath));
return 0;
}
}
return 1; /* haven't found that ACL type. */
}
static BOOL aixjfs2_process_smbacl(files_struct *fsp, SMB4ACL_T *smbacl)
{
SMB4ACE_T *smbace;
TALLOC_CTX *mem_ctx;
nfs4_acl_int_t *jfs2acl;
int32_t entryLen;
uint32 aclLen, naces;
int rc;
acl_type_t acltype;
DEBUG(10, ("jfs2_process_smbacl invoked on %s\n", fsp->fsp_name));
/* no need to be freed which is alloced with mem_ctx */
mem_ctx = main_loop_talloc_get();
entryLen = sizeof(nfs4_ace_int_t);
if (entryLen & 0x03)
entryLen = entryLen + 4 - (entryLen%4);
naces = smb_get_naces(smbacl);
aclLen = ACL_V4_SIZ + naces * entryLen;
jfs2acl = (nfs4_acl_int_t *)talloc_size(mem_ctx, aclLen);
if (jfs2acl==NULL) {
DEBUG(0, ("talloc_size failed\n"));
errno = ENOMEM;
return False;
}
jfs2acl->aclLength = ACL_V4_SIZ;
jfs2acl->aclVersion = NFS4_ACL_INT_STRUCT_VERSION;
jfs2acl->aclEntryN = 0;
for(smbace = smb_first_ace4(smbacl); smbace!=NULL; smbace = smb_next_ace4(smbace))
{
SMB_ACE4PROP_T *aceprop = smb_get_ace4(smbace);
nfs4_ace_int_t *jfs2_ace = (nfs4_ace_int_t *)(((char *)jfs2acl) + jfs2acl->aclLength);
memset(jfs2_ace, 0, entryLen);
jfs2_ace->entryLen = entryLen; /* won't store textual "who" */
jfs2_ace->aceType = aceprop->aceType; /* only ACCES|DENY supported by jfs2 */
jfs2_ace->aceFlags = aceprop->aceFlags;
jfs2_ace->aceMask = aceprop->aceMask;
jfs2_ace->flags = (aceprop->flags&SMB_ACE4_ID_SPECIAL) ? ACE4_ID_SPECIAL : 0;
/* don't care it's real content is only 16 or 32 bit */
jfs2_ace->aceWho.id = aceprop->who.id;
/* iterate to the next jfs2 ace */
jfs2acl->aclLength += jfs2_ace->entryLen;
jfs2acl->aclEntryN++;
}
SMB_ASSERT(jfs2acl->aclEntryN==naces);
/* Don't query it (again) */
memset(&acltype, 0, sizeof(acl_type_t));
acltype.u64 = ACL_NFS4;
/* won't set S_ISUID - the only one JFS2/NFS4 accepts */
rc = aclx_put(
fsp->fsp_name,
SET_ACL, /* set only the ACL, not mode bits */
acltype, /* not a pointer !!! */
jfs2acl,
jfs2acl->aclLength,
0 /* don't set here mode bits */
);
if (rc) {
DEBUG(8, ("aclx_put failed with %s\n", strerror(errno)));
return False;
}
DEBUG(10, ("jfs2_process_smbacl succeeded.\n"));
return True;
}
static BOOL aixjfs2_set_nt_acl_common(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
{
acl_type_t acl_type_info;
BOOL result = False;
int rc;
rc = aixjfs2_query_acl_support(
fsp->fsp_name,
ACL_NFS4,
&acl_type_info);
if (rc==0)
{
result = smb_set_nt_acl_nfs4(
fsp, security_info_sent, psd,
aixjfs2_process_smbacl);
} else if (rc==1) { /* assume POSIX ACL - by default... */
result = set_nt_acl(fsp, security_info_sent, psd);
} else
result = False; /* query failed */
return result;
}
BOOL aixjfs2_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info_sent, SEC_DESC *psd)
{
return aixjfs2_set_nt_acl_common(fsp, security_info_sent, psd);
}
BOOL aixjfs2_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info_sent, SEC_DESC *psd)
{
return aixjfs2_set_nt_acl_common(fsp, security_info_sent, psd);
}
int aixjfs2_sys_acl_set_file(vfs_handle_struct *handle,
const char *name,
SMB_ACL_TYPE_T type,
SMB_ACL_T theacl)
{
struct acl *acl_aixc;
acl_type_t acl_type_info;
int rc;
DEBUG(10, ("aixjfs2_sys_acl_set_file invoked for %s", name));
rc = aixjfs2_query_acl_support((char *)name, ACL_AIXC, &acl_type_info);
if (rc) {
DEBUG(8, ("jfs2_set_nt_acl: AIXC support not found\n"));
return -1;
}
acl_aixc = aixacl_smb_to_aixacl(type, theacl);
if (!acl_aixc)
return -1;
rc = aclx_put(
(char *)name,
SET_ACL, /* set only the ACL, not mode bits */
acl_type_info,
acl_aixc,
acl_aixc->acl_len,
0
);
if (rc) {
DEBUG(2, ("aclx_put failed with %s for %s\n",
strerror(errno), name));
return -1;
}
return 0;
}
int aixjfs2_sys_acl_set_fd(vfs_handle_struct *handle,
files_struct *fsp,
int fd, SMB_ACL_T theacl)
{
struct acl *acl_aixc;
acl_type_t acl_type_info;
int rc;
DEBUG(10, ("aixjfs2_sys_acl_set_fd invoked for %s", fsp->fsp_name));
rc = aixjfs2_query_acl_support(fsp->fsp_name, ACL_AIXC, &acl_type_info);
if (rc) {
DEBUG(8, ("jfs2_set_nt_acl: AIXC support not found\n"));
return -1;
}
acl_aixc = aixacl_smb_to_aixacl(SMB_ACL_TYPE_ACCESS, theacl);
if (!acl_aixc)
return -1;
rc = aclx_fput(
fd,
SET_ACL, /* set only the ACL, not mode bits */
acl_type_info,
acl_aixc,
acl_aixc->acl_len,
0
);
if (rc) {
DEBUG(2, ("aclx_fput failed with %s for %s\n",
strerror(errno), fsp->fsp_name));
return -1;
}
return 0;
}
int aixjfs2_sys_acl_delete_def_file(vfs_handle_struct *handle,
const char *path)
{
/* Not available under AIXC ACL */
/* Don't report here any error otherwise */
/* upper layer will break the normal execution */
return 0;
}
/* VFS operations structure */
static vfs_op_tuple aixjfs2_ops[] =
{
{SMB_VFS_OP(aixjfs2_fget_nt_acl),
SMB_VFS_OP_FGET_NT_ACL,
SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(aixjfs2_get_nt_acl),
SMB_VFS_OP_GET_NT_ACL,
SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(aixjfs2_fset_nt_acl),
SMB_VFS_OP_FSET_NT_ACL,
SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(aixjfs2_set_nt_acl),
SMB_VFS_OP_SET_NT_ACL,
SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(aixjfs2_sys_acl_get_file),
SMB_VFS_OP_SYS_ACL_GET_FILE,
SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(aixjfs2_sys_acl_get_fd),
SMB_VFS_OP_SYS_ACL_GET_FD,
SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(aixjfs2_sys_acl_set_file),
SMB_VFS_OP_SYS_ACL_SET_FILE,
SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(aixjfs2_sys_acl_set_fd),
SMB_VFS_OP_SYS_ACL_SET_FD,
SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(aixjfs2_sys_acl_delete_def_file),
SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE,
SMB_VFS_LAYER_TRANSPARENT},
{SMB_VFS_OP(NULL),
SMB_VFS_OP_NOOP,
SMB_VFS_LAYER_NOOP}
};
NTSTATUS vfs_aixacl2_init(void)
{
return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, AIXACL2_MODULE_NAME,
aixjfs2_ops);
}

View File

@ -901,7 +901,7 @@ static mode_t map_nt_perms( SEC_ACCESS sec_access, int type)
Unpack a SEC_DESC into a UNIX owner and group.
****************************************************************************/
static BOOL unpack_nt_owners(int snum, SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, SEC_DESC *psd)
BOOL unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, SEC_DESC *psd)
{
DOM_SID owner_sid;
DOM_SID grp_sid;
@ -2989,7 +2989,7 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc)
then allow chown to the currently authenticated user.
****************************************************************************/
static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid)
int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid)
{
int ret;
files_struct *fsp;
@ -3105,7 +3105,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
* Unpack the user/group/world id's.
*/
if (!unpack_nt_owners( SNUM(conn), &sbuf, &user, &grp, security_info_sent, psd)) {
if (!unpack_nt_owners( SNUM(conn), &user, &grp, security_info_sent, psd)) {
return False;
}