#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
{
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);
-
-static SMB_ACL4_INT_T *get_validated_aclint(SMB4ACL_T *acl)
+static SMB_ACL4_INT_T *get_validated_aclint(SMB4ACL_T *theacl)
{
- SMB_ACL4_INT_T *aclint = (SMB_ACL4_INT_T *)acl;
- if (acl==NULL)
+ SMB_ACL4_INT_T *aclint = (SMB_ACL4_INT_T *)theacl;
+ if (theacl==NULL)
{
DEBUG(2, ("acl is NULL\n"));
errno = EINVAL;
SMB4ACL_T *smb_create_smb4acl(void)
{
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)
+ SMB_ACL4_INT_T *theacl = (SMB_ACL4_INT_T *)TALLOC_ZERO_SIZE(mem_ctx, sizeof(SMB_ACL4_INT_T));
+ if (theacl==NULL)
{
DEBUG(0, ("TALLOC_SIZE failed\n"));
errno = ENOMEM;
return NULL;
}
- acl->magic = SMB_ACL4_INT_MAGIC;
- /* acl->first, last = NULL not needed */
- return (SMB4ACL_T *)acl;
+ theacl->magic = SMB_ACL4_INT_MAGIC;
+ /* theacl->first, last = NULL not needed */
+ return (SMB4ACL_T *)theacl;
}
-SMB4ACE_T *smb_add_ace4(SMB4ACL_T *acl, SMB_ACE4PROP_T *prop)
+SMB4ACE_T *smb_add_ace4(SMB4ACL_T *theacl, SMB_ACE4PROP_T *prop)
{
- SMB_ACL4_INT_T *aclint = get_validated_aclint(acl);
+ SMB_ACL4_INT_T *aclint = get_validated_aclint(theacl);
TALLOC_CTX *mem_ctx = talloc_tos();
SMB_ACE4_INT_T *ace;
return (SMB4ACE_T *)aceint->next;
}
-SMB4ACE_T *smb_first_ace4(SMB4ACL_T *acl)
+SMB4ACE_T *smb_first_ace4(SMB4ACL_T *theacl)
{
- SMB_ACL4_INT_T *aclint = get_validated_aclint(acl);
+ SMB_ACL4_INT_T *aclint = get_validated_aclint(theacl);
if (aclint==NULL)
return NULL;
return (SMB4ACE_T *)aclint->first;
}
-uint32 smb_get_naces(SMB4ACL_T *acl)
+uint32 smb_get_naces(SMB4ACL_T *theacl)
{
- SMB_ACL4_INT_T *aclint = get_validated_aclint(acl);
+ SMB_ACL4_INT_T *aclint = get_validated_aclint(theacl);
if (aclint==NULL)
return 0;
return 0;
}
-static bool smbacl4_nfs42win(TALLOC_CTX *mem_ctx, SMB4ACL_T *acl, /* in */
+static bool smbacl4_nfs42win(TALLOC_CTX *mem_ctx, SMB4ACL_T *theacl, /* in */
DOM_SID *psid_owner, /* in */
DOM_SID *psid_group, /* in */
+ bool is_directory, /* in */
SEC_ACE **ppnt_ace_list, /* out */
int *pgood_aces /* out */
)
{
- SMB_ACL4_INT_T *aclint = (SMB_ACL4_INT_T *)acl;
+ SMB_ACL4_INT_T *aclint = (SMB_ACL4_INT_T *)theacl;
SMB_ACE4_INT_T *aceint;
SEC_ACE *nt_ace_list = NULL;
int good_aces = 0;
DEBUG(10, ("smbacl_nfs42win entered"));
- aclint = get_validated_aclint(acl);
- /* We do not check for naces being 0 or acl being NULL here because it is done upstream */
+ aclint = get_validated_aclint(theacl);
+ /* We do not check for naces being 0 or theacl 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)
}
for (aceint=aclint->first; aceint!=NULL; aceint=(SMB_ACE4_INT_T *)aceint->next) {
- SEC_ACCESS mask;
+ uint32_t mask;
DOM_SID sid;
SMB_ACE4PROP_T *ace = &aceint->prop;
DEBUG(10, ("mapped %d to %s\n", ace->who.id,
sid_string_dbg(&sid)));
- init_sec_access(&mask, ace->aceMask);
+ if (is_directory && (ace->aceMask & SMB_ACE4_ADD_FILE)) {
+ ace->aceMask |= SMB_ACE4_DELETE_CHILD;
+ }
+
+ mask = ace->aceMask;
init_sec_ace(&nt_ace_list[good_aces++], &sid,
ace->aceType, mask,
ace->aceFlags & 0xf);
static NTSTATUS smb_get_nt_acl_nfs4_common(const SMB_STRUCT_STAT *sbuf,
uint32 security_info,
- SEC_DESC **ppdesc, SMB4ACL_T *acl)
+ SEC_DESC **ppdesc, SMB4ACL_T *theacl)
{
int good_aces = 0;
DOM_SID sid_owner, sid_group;
SEC_ACL *psa = NULL;
TALLOC_CTX *mem_ctx = talloc_tos();
- if (acl==NULL || smb_get_naces(acl)==0)
+ if (theacl==NULL || smb_get_naces(theacl)==0)
return NT_STATUS_ACCESS_DENIED; /* special because we
* shouldn't alloc 0 for
* win */
- uid_to_sid(&sid_owner, sbuf->st_uid);
- gid_to_sid(&sid_group, sbuf->st_gid);
+ uid_to_sid(&sid_owner, sbuf->st_ex_uid);
+ gid_to_sid(&sid_group, sbuf->st_ex_gid);
- if (smbacl4_nfs42win(mem_ctx, acl, &sid_owner, &sid_group, &nt_ace_list, &good_aces)==False) {
+ if (smbacl4_nfs42win(mem_ctx, theacl, &sid_owner, &sid_group,
+ S_ISDIR(sbuf->st_ex_mode),
+ &nt_ace_list, &good_aces)==False) {
DEBUG(8,("smbacl4_nfs42win failed\n"));
return map_nt_error_from_unix(errno);
}
}
DEBUG(10, ("smb_get_nt_acl_nfs4_common successfully exited with sd_size %d\n",
- ndr_size_security_descriptor(*ppdesc, 0)));
+ (int)ndr_size_security_descriptor(*ppdesc, NULL, 0)));
return NT_STATUS_OK;
}
NTSTATUS smb_fget_nt_acl_nfs4(files_struct *fsp,
uint32 security_info,
- SEC_DESC **ppdesc, SMB4ACL_T *acl)
+ SEC_DESC **ppdesc, SMB4ACL_T *theacl)
{
SMB_STRUCT_STAT sbuf;
return map_nt_error_from_unix(errno);
}
- return smb_get_nt_acl_nfs4_common(&sbuf, security_info, ppdesc, acl);
+ return smb_get_nt_acl_nfs4_common(&sbuf, security_info, ppdesc, theacl);
}
NTSTATUS smb_get_nt_acl_nfs4(struct connection_struct *conn,
const char *name,
uint32 security_info,
- SEC_DESC **ppdesc, SMB4ACL_T *acl)
+ SEC_DESC **ppdesc, SMB4ACL_T *theacl)
{
SMB_STRUCT_STAT sbuf;
return map_nt_error_from_unix(errno);
}
- return smb_get_nt_acl_nfs4_common(&sbuf, security_info, ppdesc, acl);
+ return smb_get_nt_acl_nfs4_common(&sbuf, security_info, ppdesc, theacl);
}
enum smbacl4_mode_enum {e_simple=0, e_special=1};
return 0;
}
-static void smbacl4_dump_nfs4acl(int level, SMB4ACL_T *acl)
+static void smbacl4_dump_nfs4acl(int level, SMB4ACL_T *theacl)
{
- SMB_ACL4_INT_T *aclint = get_validated_aclint(acl);
+ SMB_ACL4_INT_T *aclint = get_validated_aclint(theacl);
SMB_ACE4_INT_T *aceint;
DEBUG(level, ("NFS4ACL: size=%d\n", aclint->naces));
* return ace if found matching; otherwise NULL
*/
static SMB_ACE4PROP_T *smbacl4_find_equal_special(
- SMB4ACL_T *acl,
+ SMB4ACL_T *theacl,
SMB_ACE4PROP_T *aceNew)
{
- SMB_ACL4_INT_T *aclint = get_validated_aclint(acl);
+ SMB_ACL4_INT_T *aclint = get_validated_aclint(theacl);
SMB_ACE4_INT_T *aceint;
for(aceint = aclint->first; aceint!=NULL; aceint=(SMB_ACE4_INT_T *)aceint->next) {
smbacl4_vfs_params *params,
uid_t ownerUID,
gid_t ownerGID,
- SEC_ACE *ace_nt, /* input */
+ const SEC_ACE *ace_nt, /* input */
SMB_ACE4PROP_T *ace_v4 /* output */
)
{
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));
static int smbacl4_MergeIgnoreReject(
enum smbacl4_acedup_enum acedup,
- SMB4ACL_T *acl, /* may modify it */
+ SMB4ACL_T *theacl, /* 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);
+ SMB_ACE4PROP_T *ace4found = smbacl4_find_equal_special(theacl, ace);
if (ace4found)
{
switch(acedup)
static SMB4ACL_T *smbacl4_win2nfs4(
const char *filename,
- SEC_ACL *dacl,
+ const SEC_ACL *dacl,
smbacl4_vfs_params *pparams,
uid_t ownerUID,
gid_t ownerGID
)
{
- SMB4ACL_T *acl;
+ SMB4ACL_T *theacl;
uint32 i;
TALLOC_CTX *mem_ctx = talloc_tos();
DEBUG(10, ("smbacl4_win2nfs4 invoked\n"));
- acl = smb_create_smb4acl();
- if (acl==NULL)
+ theacl = smb_create_smb4acl();
+ if (theacl==NULL)
return NULL;
for(i=0; i<dacl->num_aces; i++) {
}
if (pparams->acedup!=e_dontcare) {
- if (smbacl4_MergeIgnoreReject(pparams->acedup, acl,
+ if (smbacl4_MergeIgnoreReject(pparams->acedup, theacl,
&ace_v4, &addNewACE, i))
return NULL;
}
if (addNewACE)
- smb_add_ace4(acl, &ace_v4);
+ smb_add_ace4(theacl, &ace_v4);
}
- return acl;
+ return theacl;
}
NTSTATUS smb_set_nt_acl_nfs4(files_struct *fsp,
uint32 security_info_sent,
- SEC_DESC *psd,
+ const SEC_DESC *psd,
set_nfs4acl_native_fn_t set_nfs4_native)
{
smbacl4_vfs_params params;
- SMB4ACL_T *acl = NULL;
+ SMB4ACL_T *theacl = NULL;
bool result;
SMB_STRUCT_STAT sbuf;
- bool need_chown = False;
+ bool set_acl_as_root = false;
uid_t newUID = (uid_t)-1;
gid_t newGID = (gid_t)-1;
+ int saved_errno;
DEBUG(10, ("smb_set_nt_acl_nfs4 invoked for %s\n", fsp->fsp_name));
DEBUG(8, ("unpack_nt_owners failed"));
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 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 */
+ if (((newUID != (uid_t)-1) && (sbuf.st_ex_uid != newUID)) ||
+ ((newGID != (gid_t)-1) && (sbuf.st_ex_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)));
+ 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);
+
+ /* If we successfully chowned, we know we must
+ * be able to set the acl, so do it as root.
+ */
+ set_acl_as_root = true;
}
}
- if ((security_info_sent & DACL_SECURITY_INFORMATION)!=0 && psd->dacl!=NULL)
- {
- acl = smbacl4_win2nfs4(fsp->fsp_name, psd->dacl, ¶ms, sbuf.st_uid, sbuf.st_gid);
- if (!acl)
- return map_nt_error_from_unix(errno);
+ if (!(security_info_sent & DACL_SECURITY_INFORMATION) || psd->dacl ==NULL) {
+ DEBUG(10, ("no dacl found; security_info_sent = 0x%x\n", security_info_sent));
+ return NT_STATUS_OK;
+ }
- smbacl4_dump_nfs4acl(10, acl);
+ theacl = smbacl4_win2nfs4(fsp->fsp_name, psd->dacl, ¶ms, sbuf.st_uid, sbuf.st_gid);
+ if (!theacl)
+ return map_nt_error_from_unix(errno);
- result = set_nfs4_native(fsp, acl);
- if (result!=True)
- {
- DEBUG(10, ("set_nfs4_native failed with %s\n", strerror(errno)));
- return map_nt_error_from_unix(errno);
- }
- } else
- DEBUG(10, ("no dacl found; security_info_sent = 0x%x\n", security_info_sent));
+ smbacl4_dump_nfs4acl(10, theacl);
- /* 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));
+ if (set_acl_as_root) {
+ become_root();
+ }
+ result = set_nfs4_native(fsp, theacl);
+ saved_errno = errno;
+ if (set_acl_as_root) {
+ unbecome_root();
+ }
+ if (result!=True) {
+ errno = saved_errno;
+ DEBUG(10, ("set_nfs4_native failed with %s\n", strerror(errno)));
+ return map_nt_error_from_unix(errno);
}
DEBUG(10, ("smb_set_nt_acl_nfs4 succeeded\n"));