Beispiel #1
0
        /// <exception cref="System.IO.IOException"/>
        private static void UnprotectedRemoveAcl(FSDirectory fsd, INodesInPath iip)
        {
            System.Diagnostics.Debug.Assert(fsd.HasWriteLock());
            INode      inode      = FSDirectory.ResolveLastINode(iip);
            int        snapshotId = iip.GetLatestSnapshotId();
            AclFeature f          = inode.GetAclFeature();

            if (f == null)
            {
                return;
            }
            FsPermission     perm           = inode.GetFsPermission();
            IList <AclEntry> featureEntries = AclStorage.GetEntriesFromAclFeature(f);

            if (featureEntries[0].GetScope() == AclEntryScope.Access)
            {
                // Restore group permissions from the feature's entry to permission
                // bits, overwriting the mask, which is not part of a minimal ACL.
                AclEntry groupEntryKey = new AclEntry.Builder().SetScope(AclEntryScope.Access).SetType
                                             (AclEntryType.Group).Build();
                int groupEntryIndex = Sharpen.Collections.BinarySearch(featureEntries, groupEntryKey
                                                                       , AclTransformation.AclEntryComparator);
                System.Diagnostics.Debug.Assert(groupEntryIndex >= 0);
                FsAction     groupPerm = featureEntries[groupEntryIndex].GetPermission();
                FsPermission newPerm   = new FsPermission(perm.GetUserAction(), groupPerm, perm.GetOtherAction
                                                              (), perm.GetStickyBit());
                inode.SetPermission(newPerm, snapshotId);
            }
            inode.RemoveAclFeature(snapshotId);
        }
Beispiel #2
0
        /// <summary>Reads the existing ACL of an inode.</summary>
        /// <remarks>
        /// Reads the existing ACL of an inode.  This method always returns the full
        /// logical ACL of the inode after reading relevant data from the inode's
        /// <see cref="Org.Apache.Hadoop.FS.Permission.FsPermission"/>
        /// and
        /// <see cref="AclFeature"/>
        /// .  Note that every inode
        /// logically has an ACL, even if no ACL has been set explicitly.  If the inode
        /// does not have an extended ACL, then the result is a minimal ACL consising of
        /// exactly 3 entries that correspond to the owner, group and other permissions.
        /// This method always reads the inode's current state and does not support
        /// querying by snapshot ID.  This is because the method is intended to support
        /// ACL modification APIs, which always apply a delta on top of current state.
        /// </remarks>
        /// <param name="inode">INode to read</param>
        /// <returns>List<AclEntry> containing all logical inode ACL entries</returns>
        public static IList <AclEntry> ReadINodeLogicalAcl(INode inode)
        {
            FsPermission perm = inode.GetFsPermission();
            AclFeature   f    = inode.GetAclFeature();

            if (f == null)
            {
                return(AclUtil.GetMinimalAcl(perm));
            }
            IList <AclEntry> existingAcl;
            // Split ACL entries stored in the feature into access vs. default.
            IList <AclEntry> featureEntries = GetEntriesFromAclFeature(f);
            ScopedAclEntries scoped         = new ScopedAclEntries(featureEntries);
            IList <AclEntry> accessEntries  = scoped.GetAccessEntries();
            IList <AclEntry> defaultEntries = scoped.GetDefaultEntries();

            // Pre-allocate list size for the explicit entries stored in the feature
            // plus the 3 implicit entries (owner, group and other) from the permission
            // bits.
            existingAcl = Lists.NewArrayListWithCapacity(featureEntries.Count + 3);
            if (!accessEntries.IsEmpty())
            {
                // Add owner entry implied from user permission bits.
                existingAcl.AddItem(new AclEntry.Builder().SetScope(AclEntryScope.Access).SetType
                                        (AclEntryType.User).SetPermission(perm.GetUserAction()).Build());
                // Next add all named user and group entries taken from the feature.
                Sharpen.Collections.AddAll(existingAcl, accessEntries);
                // Add mask entry implied from group permission bits.
                existingAcl.AddItem(new AclEntry.Builder().SetScope(AclEntryScope.Access).SetType
                                        (AclEntryType.Mask).SetPermission(perm.GetGroupAction()).Build());
                // Add other entry implied from other permission bits.
                existingAcl.AddItem(new AclEntry.Builder().SetScope(AclEntryScope.Access).SetType
                                        (AclEntryType.Other).SetPermission(perm.GetOtherAction()).Build());
            }
            else
            {
                // It's possible that there is a default ACL but no access ACL. In this
                // case, add the minimal access ACL implied by the permission bits.
                Sharpen.Collections.AddAll(existingAcl, AclUtil.GetMinimalAcl(perm));
            }
            // Add all default entries after the access entries.
            Sharpen.Collections.AddAll(existingAcl, defaultEntries);
            // The above adds entries in the correct order, so no need to sort here.
            return(existingAcl);
        }
Beispiel #3
0
 /// <exception cref="Org.Apache.Hadoop.Security.AccessControlException"/>
 private static void CheckXAttrChangeAccess(FSDirectory fsd, INodesInPath iip, XAttr
                                            xAttr, FSPermissionChecker pc)
 {
     if (fsd.IsPermissionEnabled() && xAttr.GetNameSpace() == XAttr.NameSpace.User)
     {
         INode inode = iip.GetLastINode();
         if (inode != null && inode.IsDirectory() && inode.GetFsPermission().GetStickyBit(
                 ))
         {
             if (!pc.IsSuperUser())
             {
                 fsd.CheckOwner(pc, iip);
             }
         }
         else
         {
             fsd.CheckPathAccess(pc, iip, FsAction.Write);
         }
     }
 }
Beispiel #4
0
        /// <exception cref="System.IO.IOException"/>
        internal static AclStatus GetAclStatus(FSDirectory fsd, string src)
        {
            CheckAclsConfigFlag(fsd);
            FSPermissionChecker pc = fsd.GetPermissionChecker();

            byte[][] pathComponents = FSDirectory.GetPathComponentsForReservedPath(src);
            src = fsd.ResolvePath(pc, src, pathComponents);
            string srcs = FSDirectory.NormalizePath(src);

            fsd.ReadLock();
            try
            {
                // There is no real inode for the path ending in ".snapshot", so return a
                // non-null, unpopulated AclStatus.  This is similar to getFileInfo.
                if (srcs.EndsWith(HdfsConstants.SeparatorDotSnapshotDir) && fsd.GetINode4DotSnapshot
                        (srcs) != null)
                {
                    return(new AclStatus.Builder().Owner(string.Empty).Group(string.Empty).Build());
                }
                INodesInPath iip = fsd.GetINodesInPath(srcs, true);
                if (fsd.IsPermissionEnabled())
                {
                    fsd.CheckTraverse(pc, iip);
                }
                INode            inode      = FSDirectory.ResolveLastINode(iip);
                int              snapshotId = iip.GetPathSnapshotId();
                IList <AclEntry> acl        = AclStorage.ReadINodeAcl(fsd.GetAttributes(src, inode.GetLocalNameBytes
                                                                                            (), inode, snapshotId));
                FsPermission fsPermission = inode.GetFsPermission(snapshotId);
                return(new AclStatus.Builder().Owner(inode.GetUserName()).Group(inode.GetGroupName
                                                                                    ()).StickyBit(fsPermission.GetStickyBit()).SetPermission(fsPermission).AddEntries
                           (acl).Build());
            }
            finally
            {
                fsd.ReadUnlock();
            }
        }
Beispiel #5
0
        /// <summary>Updates an inode with a new ACL.</summary>
        /// <remarks>
        /// Updates an inode with a new ACL.  This method takes a full logical ACL and
        /// stores the entries to the inode's
        /// <see cref="Org.Apache.Hadoop.FS.Permission.FsPermission"/>
        /// and
        /// <see cref="AclFeature"/>
        /// .
        /// </remarks>
        /// <param name="inode">INode to update</param>
        /// <param name="newAcl">List<AclEntry> containing new ACL entries</param>
        /// <param name="snapshotId">int latest snapshot ID of inode</param>
        /// <exception cref="Org.Apache.Hadoop.Hdfs.Protocol.AclException">if the ACL is invalid for the given inode
        ///     </exception>
        /// <exception cref="Org.Apache.Hadoop.Hdfs.Protocol.QuotaExceededException">if quota limit is exceeded
        ///     </exception>
        public static void UpdateINodeAcl(INode inode, IList <AclEntry> newAcl, int snapshotId
                                          )
        {
            System.Diagnostics.Debug.Assert(newAcl.Count >= 3);
            FsPermission perm = inode.GetFsPermission();
            FsPermission newPerm;

            if (!AclUtil.IsMinimalAcl(newAcl))
            {
                // This is an extended ACL.  Split entries into access vs. default.
                ScopedAclEntries scoped         = new ScopedAclEntries(newAcl);
                IList <AclEntry> accessEntries  = scoped.GetAccessEntries();
                IList <AclEntry> defaultEntries = scoped.GetDefaultEntries();
                // Only directories may have a default ACL.
                if (!defaultEntries.IsEmpty() && !inode.IsDirectory())
                {
                    throw new AclException("Invalid ACL: only directories may have a default ACL.");
                }
                // Attach entries to the feature.
                if (inode.GetAclFeature() != null)
                {
                    inode.RemoveAclFeature(snapshotId);
                }
                inode.AddAclFeature(CreateAclFeature(accessEntries, defaultEntries), snapshotId);
                newPerm = CreateFsPermissionForExtendedAcl(accessEntries, perm);
            }
            else
            {
                // This is a minimal ACL.  Remove the ACL feature if it previously had one.
                if (inode.GetAclFeature() != null)
                {
                    inode.RemoveAclFeature(snapshotId);
                }
                newPerm = CreateFsPermissionForMinimalAcl(newAcl, perm);
            }
            inode.SetPermission(newPerm, snapshotId);
        }
Beispiel #6
0
        /// <summary>
        /// If a default ACL is defined on a parent directory, then copies that default
        /// ACL to a newly created child file or directory.
        /// </summary>
        /// <param name="child">INode newly created child</param>
        public static void CopyINodeDefaultAcl(INode child)
        {
            INodeDirectory parent           = child.GetParent();
            AclFeature     parentAclFeature = parent.GetAclFeature();

            if (parentAclFeature == null || !(child.IsFile() || child.IsDirectory()))
            {
                return;
            }
            // Split parent's entries into access vs. default.
            IList <AclEntry> featureEntries       = GetEntriesFromAclFeature(parent.GetAclFeature());
            ScopedAclEntries scopedEntries        = new ScopedAclEntries(featureEntries);
            IList <AclEntry> parentDefaultEntries = scopedEntries.GetDefaultEntries();

            // The parent may have an access ACL but no default ACL.  If so, exit.
            if (parentDefaultEntries.IsEmpty())
            {
                return;
            }
            // Pre-allocate list size for access entries to copy from parent.
            IList <AclEntry> accessEntries = Lists.NewArrayListWithCapacity(parentDefaultEntries
                                                                            .Count);
            FsPermission childPerm = child.GetFsPermission();
            // Copy each default ACL entry from parent to new child's access ACL.
            bool parentDefaultIsMinimal = AclUtil.IsMinimalAcl(parentDefaultEntries);

            foreach (AclEntry entry in parentDefaultEntries)
            {
                AclEntryType     type    = entry.GetType();
                string           name    = entry.GetName();
                AclEntry.Builder builder = new AclEntry.Builder().SetScope(AclEntryScope.Access).
                                           SetType(type).SetName(name);
                // The child's initial permission bits are treated as the mode parameter,
                // which can filter copied permission values for owner, mask and other.
                FsAction permission;
                if (type == AclEntryType.User && name == null)
                {
                    permission = entry.GetPermission().And(childPerm.GetUserAction());
                }
                else
                {
                    if (type == AclEntryType.Group && parentDefaultIsMinimal)
                    {
                        // This only happens if the default ACL is a minimal ACL: exactly 3
                        // entries corresponding to owner, group and other.  In this case,
                        // filter the group permissions.
                        permission = entry.GetPermission().And(childPerm.GetGroupAction());
                    }
                    else
                    {
                        if (type == AclEntryType.Mask)
                        {
                            // Group bits from mode parameter filter permission of mask entry.
                            permission = entry.GetPermission().And(childPerm.GetGroupAction());
                        }
                        else
                        {
                            if (type == AclEntryType.Other)
                            {
                                permission = entry.GetPermission().And(childPerm.GetOtherAction());
                            }
                            else
                            {
                                permission = entry.GetPermission();
                            }
                        }
                    }
                }
                builder.SetPermission(permission);
                accessEntries.AddItem(builder.Build());
            }
            // A new directory also receives a copy of the parent's default ACL.
            IList <AclEntry> defaultEntries = child.IsDirectory() ? parentDefaultEntries : Sharpen.Collections
                                              .EmptyList <AclEntry>();
            FsPermission newPerm;

            if (!AclUtil.IsMinimalAcl(accessEntries) || !defaultEntries.IsEmpty())
            {
                // Save the new ACL to the child.
                child.AddAclFeature(CreateAclFeature(accessEntries, defaultEntries));
                newPerm = CreateFsPermissionForExtendedAcl(accessEntries, childPerm);
            }
            else
            {
                // The child is receiving a minimal ACL.
                newPerm = CreateFsPermissionForMinimalAcl(accessEntries, childPerm);
            }
            child.SetPermission(newPerm);
        }