Fix a size_t/int warning
[ira/wip.git] / source3 / modules / nfs4_acls.c
index 0c3d010dcde64553487648b50ef23dc6e46d619f..0941eb94f5fe5fcbd9eda683607ef00256c54670 100644 (file)
@@ -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
 {
@@ -42,15 +44,10 @@ 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);
-
-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;
@@ -86,21 +83,21 @@ static SMB_ACE4_INT_T *get_validated_aceint(SMB4ACE_T *ace)
 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;
 
@@ -146,18 +143,18 @@ SMB4ACE_T *smb_next_ace4(SMB4ACE_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;
 
@@ -198,22 +195,23 @@ static int smbacl4_fGetFileOwner(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 *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)
@@ -224,7 +222,7 @@ static bool smbacl4_nfs42win(TALLOC_CTX *mem_ctx, SMB4ACL_T *acl, /* in */
        }
 
        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;
 
@@ -259,7 +257,11 @@ static bool smbacl4_nfs42win(TALLOC_CTX *mem_ctx, SMB4ACL_T *acl, /* in */
                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);
@@ -273,7 +275,7 @@ static bool smbacl4_nfs42win(TALLOC_CTX *mem_ctx, SMB4ACL_T *acl, /* in */
 
 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;
@@ -282,15 +284,17 @@ static NTSTATUS smb_get_nt_acl_nfs4_common(const SMB_STRUCT_STAT *sbuf,
        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);
        }
@@ -312,14 +316,14 @@ 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",
-                  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;
 
@@ -329,13 +333,13 @@ NTSTATUS smb_fget_nt_acl_nfs4(files_struct *fsp,
                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;
 
@@ -345,7 +349,7 @@ NTSTATUS smb_get_nt_acl_nfs4(struct connection_struct *conn,
                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};
@@ -396,9 +400,9 @@ static int smbacl4_get_vfs_params(
        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));
@@ -420,10 +424,10 @@ static void smbacl4_dump_nfs4acl(int level, SMB4ACL_T *acl)
  * 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) {
@@ -517,7 +521,7 @@ static bool smbacl4_fill_ace4(
        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 */
 )
 {
@@ -529,6 +533,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));
@@ -613,14 +619,14 @@ static bool smbacl4_fill_ace4(
 
 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)
@@ -647,20 +653,20 @@ static int smbacl4_MergeIgnoreReject(
 
 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++) {
@@ -677,31 +683,32 @@ static SMB4ACL_T *smbacl4_win2nfs4(
                }
 
                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));
 
@@ -727,60 +734,50 @@ NTSTATUS smb_set_nt_acl_nfs4(files_struct *fsp,
                        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, &params, 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, &params, 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"));