Implemented default ACL patch (set inherit acls = true on a per share basis).
[sfrench/samba-autobuild/.git] / source3 / smbd / posix_acls.c
index 64dd51f1934da6783667a3dc648fc8fa1a72f954..34f0b77002991aad8c1990a01a438c81377e6e7f 100644 (file)
@@ -1,6 +1,5 @@
 /*
-   Unix SMB/Netbios implementation.
-   Version 1.9.
+   Unix SMB/CIFS implementation.
    SMB NT Security Descriptor / Unix permission conversion.
    Copyright (C) Jeremy Allison 1994-2000
 
@@ -38,7 +37,7 @@ typedef struct canon_ace {
        struct canon_ace *next, *prev;
        SMB_ACL_TAG_T type;
        mode_t perms; /* Only use S_I(R|W|X)USR mode bits here. */
-       DOM_SID sid;
+       DOM_SID trustee;
        enum ace_owner owner_type;
        enum ace_attribute attr;
        posix_id unix_ug; 
@@ -103,13 +102,13 @@ static void print_canon_ace(canon_ace *pace, int num)
        fstring str;
 
        dbgtext( "canon_ace index %d. Type = %s ", num, pace->attr == ALLOW_ACE ? "allow" : "deny" );
-    dbgtext( "SID = %s ", sid_to_string( str, &pace->sid));
+       dbgtext( "SID = %s ", sid_to_string( str, &pace->trustee));
        if (pace->owner_type == UID_ACE) {
-               struct passwd *pass = sys_getpwuid(pace->unix_ug.uid);
-               dbgtext( "uid %u (%s) ", (unsigned int)pace->unix_ug.uid, pass ? pass->pw_name : "UNKNOWN");
+               char *u_name = uidtoname(pace->unix_ug.uid);
+               dbgtext( "uid %u (%s) ", (unsigned int)pace->unix_ug.uid, u_name);
        } else if (pace->owner_type == GID_ACE) {
-               struct group *grp = getgrgid(pace->unix_ug.gid);
-               dbgtext( "gid %u (%s) ", (unsigned int)pace->unix_ug.gid, grp ? grp->gr_name : "UNKNOWN");
+               char *g_name = gidtoname(pace->unix_ug.gid);
+               dbgtext( "gid %u (%s) ", (unsigned int)pace->unix_ug.gid, g_name);
        } else
                dbgtext( "other ");
        switch (pace->type) {
@@ -243,7 +242,7 @@ static void merge_aces( canon_ace **pp_list_head )
 
                        curr_ace_next = curr_ace->next; /* Save the link in case of delete. */
 
-                       if (sid_equal(&curr_ace->sid, &curr_ace_outer->sid) &&
+                       if (sid_equal(&curr_ace->trustee, &curr_ace_outer->trustee) &&
                                (curr_ace->attr == curr_ace_outer->attr)) {
 
                                if( DEBUGLVL( 10 )) {
@@ -283,7 +282,7 @@ static void merge_aces( canon_ace **pp_list_head )
                         * we've put on the ACL, we know the deny must be the first one.
                         */
 
-                       if (sid_equal(&curr_ace->sid, &curr_ace_outer->sid) &&
+                       if (sid_equal(&curr_ace->trustee, &curr_ace_outer->trustee) &&
                                (curr_ace_outer->attr == DENY_ACE) && (curr_ace->attr == ALLOW_ACE)) {
 
                                if( DEBUGLVL( 10 )) {
@@ -318,6 +317,7 @@ static void merge_aces( canon_ace **pp_list_head )
 
                                        DLIST_REMOVE(list_head, curr_ace_outer);
                                        SAFE_FREE(curr_ace_outer);
+                                       break;
                                }
                        }
 
@@ -439,7 +439,8 @@ static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp,
        if (security_info_sent & OWNER_SECURITY_INFORMATION) {
                sid_copy(&owner_sid, psd->owner_sid);
                if (!sid_to_uid( &owner_sid, puser, &sid_type)) {
-                       DEBUG(3,("unpack_nt_owners: unable to validate owner sid.\n"));
+                       DEBUG(3,("unpack_nt_owners: unable to validate owner sid for %s\n",
+                                sid_string_static(&owner_sid)));
                        return False;
                }
        }
@@ -572,7 +573,7 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace,
                pace->type = SMB_ACL_USER_OBJ;
                pace->owner_type = UID_ACE;
                pace->unix_ug.uid = pst->st_uid;
-               pace->sid = *pfile_owner_sid;
+               pace->trustee = *pfile_owner_sid;
                pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRUSR, S_IWUSR, S_IXUSR);
                pace->attr = ALLOW_ACE;
 
@@ -589,7 +590,7 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace,
                pace->type = SMB_ACL_GROUP_OBJ;
                pace->owner_type = GID_ACE;
                pace->unix_ug.uid = pst->st_gid;
-               pace->sid = *pfile_grp_sid;
+               pace->trustee = *pfile_grp_sid;
                pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IRGRP, S_IWGRP, S_IXGRP);
                pace->attr = ALLOW_ACE;
 
@@ -606,7 +607,7 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace,
                pace->type = SMB_ACL_OTHER;
                pace->owner_type = WORLD_ACE;
                pace->unix_ug.world = -1;
-               pace->sid = global_sid_World;
+               pace->trustee = global_sid_World;
                pace->perms = unix_perms_to_acl_perms(pst->st_mode, S_IROTH, S_IWOTH, S_IXOTH);
                pace->attr = ALLOW_ACE;
 
@@ -688,7 +689,7 @@ static BOOL create_canon_ace_lists(files_struct *fsp,
                        if (psa1->info.mask != psa2->info.mask)
                                continue;
 
-                       if (!sid_equal(&psa1->sid, &psa2->sid))
+                       if (!sid_equal(&psa1->trustee, &psa2->trustee))
                                continue;
 
                        /*
@@ -718,10 +719,10 @@ static BOOL create_canon_ace_lists(files_struct *fsp,
                 * Ignore non-mappable SIDs (NT Authority, BUILTIN etc).
                 */
 
-               if (non_mappable_sid(&psa->sid)) {
+               if (non_mappable_sid(&psa->trustee)) {
                        fstring str;
                        DEBUG(10,("create_canon_ace_lists: ignoring non-mappable SID %s\n",
-                               sid_to_string(str, &psa->sid) ));
+                               sid_to_string(str, &psa->trustee) ));
                        continue;
                }
 
@@ -738,28 +739,28 @@ static BOOL create_canon_ace_lists(files_struct *fsp,
 
                ZERO_STRUCTP(current_ace);
 
-               sid_copy(&current_ace->sid, &psa->sid);
+               sid_copy(&current_ace->trustee, &psa->trustee);
 
                /*
                 * Try and work out if the SID is a user or group
                 * as we need to flag these differently for POSIX.
                 */
 
-               if( sid_equal(&current_ace->sid, &global_sid_World)) {
+               if( sid_equal(&current_ace->trustee, &global_sid_World)) {
                        current_ace->owner_type = WORLD_ACE;
                        current_ace->unix_ug.world = -1;
-               } else if (sid_to_uid( &current_ace->sid, &current_ace->unix_ug.uid, &sid_type)) {
+               } else if (sid_to_uid( &current_ace->trustee, &current_ace->unix_ug.uid, &sid_type)) {
                        current_ace->owner_type = UID_ACE;
-               } else if (sid_to_gid( &current_ace->sid, &current_ace->unix_ug.gid, &sid_type)) {
+               } else if (sid_to_gid( &current_ace->trustee, &current_ace->unix_ug.gid, &sid_type)) {
                        current_ace->owner_type = GID_ACE;
                } else {
                        fstring str;
 
                        free_canon_ace_list(file_ace);
                        free_canon_ace_list(dir_ace);
-                       SAFE_FREE(current_ace);
                        DEBUG(0,("create_canon_ace_lists: unable to map SID %s to uid or gid.\n",
-                               sid_to_string(str, &current_ace->sid) ));
+                               sid_to_string(str, &current_ace->trustee) ));
+                       SAFE_FREE(current_ace);
                        return False;
                }
 
@@ -775,15 +776,15 @@ static BOOL create_canon_ace_lists(files_struct *fsp,
                 * Now note what kind of a POSIX ACL this should map to.
                 */
 
-               if(sid_equal(&current_ace->sid, pfile_owner_sid)) {
+               if(sid_equal(&current_ace->trustee, pfile_owner_sid)) {
 
                        current_ace->type = SMB_ACL_USER_OBJ;
 
-               } else if( sid_equal(&current_ace->sid, pfile_grp_sid)) {
+               } else if( sid_equal(&current_ace->trustee, pfile_grp_sid)) {
 
                        current_ace->type = SMB_ACL_GROUP_OBJ;
 
-               } else if( sid_equal(&current_ace->sid, &global_sid_World)) {
+               } else if( sid_equal(&current_ace->trustee, &global_sid_World)) {
 
                        current_ace->type = SMB_ACL_OTHER;
 
@@ -925,26 +926,23 @@ Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name ));
 static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace )
 {
        extern DOM_SID global_sid_World;
-       struct passwd *pass = NULL;
-       struct group *gptr = NULL;
+       fstring u_name;
+       fstring g_name;
 
        /* "Everyone" always matches every uid. */
 
-       if (sid_equal(&group_ace->sid, &global_sid_World))
+       if (sid_equal(&group_ace->trustee, &global_sid_World))
                return True;
 
-       if (!(pass = sys_getpwuid(uid_ace->unix_ug.uid)))
-               return False;
-
-       if (!(gptr = getgrgid(group_ace->unix_ug.gid)))
-               return False;
+       fstrcpy(u_name, uidtoname(uid_ace->unix_ug.uid));
+       fstrcpy(g_name, gidtoname(group_ace->unix_ug.gid));
 
        /*
         * Due to the winbind interfaces we need to do this via names,
         * not uids/gids.
         */
 
-       return user_in_group_list(pass->pw_name, gptr->gr_name );
+       return user_in_group_list(u_name, g_name );
 }
 
 /****************************************************************************
@@ -1067,7 +1065,7 @@ static void process_deny_list( canon_ace **pp_ace_list )
                        continue;
                }
 
-               if (!sid_equal(&curr_ace->sid, &global_sid_World))
+               if (!sid_equal(&curr_ace->trustee, &global_sid_World))
                        continue;
 
                /* JRATEST - assert. */
@@ -1518,7 +1516,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_
                ace->type = tagtype;
                ace->perms = convert_permset_to_mode_t(permset);
                ace->attr = ALLOW_ACE;
-               ace->sid = sid;
+               ace->trustee = sid;
                ace->unix_ug = unix_ug;
                ace->owner_type = owner_type;
 
@@ -1719,14 +1717,26 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau
 
        if(default_ace || fsp->is_directory || fsp->fd == -1) {
                if (sys_acl_set_file(fsp->fsp_name, the_acl_type, the_acl) == -1) {
-                       DEBUG(0,("set_canon_ace_list: sys_acl_set_file type %s failed for file %s (%s).\n",
+                       /*
+                        * Some systems allow all the above calls and only fail with no ACL support
+                        * when attempting to apply the acl. HPUX with HFS is an example of this. JRA.
+                        */
+                       if (errno == ENOSYS)
+                               *pacl_set_support = False;
+                       DEBUG(2,("set_canon_ace_list: sys_acl_set_file type %s failed for file %s (%s).\n",
                                        the_acl_type == SMB_ACL_TYPE_DEFAULT ? "directory default" : "file",
                                        fsp->fsp_name, strerror(errno) ));
                        goto done;
                }
        } else {
                if (sys_acl_set_fd(fsp->fd, the_acl) == -1) {
-                       DEBUG(0,("set_canon_ace_list: sys_acl_set_file failed for file %s (%s).\n",
+                       /*
+                        * Some systems allow all the above calls and only fail with no ACL support
+                        * when attempting to apply the acl. HPUX with HFS is an example of this. JRA.
+                        */
+                       if (errno == ENOSYS)
+                               *pacl_set_support = False;
+                       DEBUG(2,("set_canon_ace_list: sys_acl_set_file failed for file %s (%s).\n",
                                        fsp->fsp_name, strerror(errno) ));
                        goto done;
                }
@@ -1937,14 +1947,14 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc)
 
                for (i = 0; i < num_acls; i++, ace = ace->next) {
                        SEC_ACCESS acc = map_canon_ace_perms(&nt_acl_type, &owner_sid, ace );
-                       init_sec_ace(&nt_ace_list[num_aces++], &ace->sid, nt_acl_type, acc, 0);
+                       init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, acc, 0);
                }
 
                ace = dir_ace;
 
                for (i = 0; i < num_dir_acls; i++, ace = ace->next) {
                        SEC_ACCESS acc = map_canon_ace_perms(&nt_acl_type, &owner_sid, ace );
-                       init_sec_ace(&nt_ace_list[num_aces++], &ace->sid, nt_acl_type, acc, 
+                       init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, acc, 
                                        SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY);
                }
 
@@ -2284,3 +2294,16 @@ int fchmod_acl(int fd, mode_t mode)
        sys_acl_free_acl(posix_acl);
        return ret;
 }
+
+BOOL directory_has_default_acl(const char *fname)
+{
+        SMB_ACL_T dir_acl = sys_acl_get_file( fname, SMB_ACL_TYPE_DEFAULT);
+        BOOL has_acl = False;
+        SMB_ACL_ENTRY_T entry;
+
+        if (dir_acl != NULL && (sys_acl_get_entry(dir_acl, SMB_ACL_FIRST_ENTRY, &entry) == 1))
+                has_acl = True;
+
+        sys_acl_free_acl(dir_acl);
+        return has_acl;
+}