/// <summary>Whether a cache pool can be accessed by the current context</summary> /// <param name="pool">CachePool being accessed</param> /// <param name="access">type of action being performed on the cache pool</param> /// <exception cref="Org.Apache.Hadoop.Security.AccessControlException">if pool cannot be accessed /// </exception> public virtual void CheckPermission(CachePool pool, FsAction access) { FsPermission mode = pool.GetMode(); if (IsSuperUser()) { return; } if (GetUser().Equals(pool.GetOwnerName()) && mode.GetUserAction().Implies(access)) { return; } if (GetGroups().Contains(pool.GetGroupName()) && mode.GetGroupAction().Implies(access )) { return; } if (mode.GetOtherAction().Implies(access)) { return; } throw new AccessControlException("Permission denied while accessing pool " + pool .GetPoolName() + ": user " + GetUser() + " does not have " + access.ToString() + " permissions."); }
/// <summary>Check whether current user have permissions to access the path.</summary> /// <remarks> /// Check whether current user have permissions to access the path. /// Traverse is always checked. /// Parent path means the parent directory for the path. /// Ancestor path means the last (the closest) existing ancestor directory /// of the path. /// Note that if the parent path exists, /// then the parent path and the ancestor path are the same. /// For example, suppose the path is "/foo/bar/baz". /// No matter baz is a file or a directory, /// the parent path is "/foo/bar". /// If bar exists, then the ancestor path is also "/foo/bar". /// If bar does not exist and foo exists, /// then the ancestor path is "/foo". /// Further, if both foo and bar do not exist, /// then the ancestor path is "/". /// </remarks> /// <param name="doCheckOwner">Require user to be the owner of the path?</param> /// <param name="ancestorAccess">The access required by the ancestor of the path.</param> /// <param name="parentAccess">The access required by the parent of the path.</param> /// <param name="access">The access required by the path.</param> /// <param name="subAccess"> /// If path is a directory, /// it is the access required of the path and all the sub-directories. /// If path is not a directory, there is no effect. /// </param> /// <param name="ignoreEmptyDir">Ignore permission checking for empty directory?</param> /// <exception cref="Org.Apache.Hadoop.Security.AccessControlException"> /// Guarded by /// <see cref="FSNamesystem.ReadLock()"/> /// Caller of this method must hold that lock. /// </exception> internal virtual void CheckPermission(INodesInPath inodesInPath, bool doCheckOwner , FsAction ancestorAccess, FsAction parentAccess, FsAction access, FsAction subAccess , bool ignoreEmptyDir) { if (Log.IsDebugEnabled()) { Log.Debug("ACCESS CHECK: " + this + ", doCheckOwner=" + doCheckOwner + ", ancestorAccess=" + ancestorAccess + ", parentAccess=" + parentAccess + ", access=" + access + ", subAccess=" + subAccess + ", ignoreEmptyDir=" + ignoreEmptyDir); } // check if (parentAccess != null) && file exists, then check sb // If resolveLink, the check is performed on the link target. int snapshotId = inodesInPath.GetPathSnapshotId(); INode[] inodes = inodesInPath.GetINodesArray(); INodeAttributes[] inodeAttrs = new INodeAttributes[inodes.Length]; byte[][] pathByNameArr = new byte[inodes.Length][]; for (int i = 0; i < inodes.Length && inodes[i] != null; i++) { if (inodes[i] != null) { pathByNameArr[i] = inodes[i].GetLocalNameBytes(); inodeAttrs[i] = GetINodeAttrs(pathByNameArr, i, inodes[i], snapshotId); } } string path = inodesInPath.GetPath(); int ancestorIndex = inodes.Length - 2; INodeAttributeProvider.AccessControlEnforcer enforcer = GetAttributesProvider().GetExternalAccessControlEnforcer (this); enforcer.CheckPermission(fsOwner, supergroup, callerUgi, inodeAttrs, inodes, pathByNameArr , snapshotId, path, ancestorIndex, doCheckOwner, ancestorAccess, parentAccess, access , subAccess, ignoreEmptyDir); }
/// <summary> /// Guarded by /// <see cref="FSNamesystem.ReadLock()"/> /// /// </summary> /// <exception cref="Org.Apache.Hadoop.Security.AccessControlException"/> private void CheckSubAccess(byte[][] pathByNameArr, int pathIdx, INode inode, int snapshotId, FsAction access, bool ignoreEmptyDir) { if (inode == null || !inode.IsDirectory()) { return; } Stack <INodeDirectory> directories = new Stack <INodeDirectory>(); for (directories.Push(inode.AsDirectory()); !directories.IsEmpty();) { INodeDirectory d = directories.Pop(); ReadOnlyList <INode> cList = d.GetChildrenList(snapshotId); if (!(cList.IsEmpty() && ignoreEmptyDir)) { //TODO have to figure this out with inodeattribute provider Check(GetINodeAttrs(pathByNameArr, pathIdx, d, snapshotId), inode.GetFullPathName (), access); } foreach (INode child in cList) { if (child.IsDirectory()) { directories.Push(child.AsDirectory()); } } } }
internal static FsAction GetPermission(int aclEntry) { int ordinal = (int)Org.Apache.Hadoop.Hdfs.Server.Namenode.AclEntryStatusFormat.Permission .Bits.Retrieve(aclEntry); return(FsAction.Values()[ordinal]); }
/// <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); }
/// <exception cref="System.IO.IOException"/> private void AssertPermissionGranted(UserGroupInformation user, string path, FsAction access) { INodesInPath iip = dir.GetINodesInPath(path, true); dir.GetPermissionChecker(Superuser, Supergroup, user).CheckPermission(iip, false, null, null, access, null, false); }
/// <summary> /// Checks for a given path whether the Other permissions on it /// imply the permission in the passed FsAction /// </summary> /// <param name="fs"/> /// <param name="path"/> /// <param name="action"/> /// <returns>true if the path in the uri is visible to all, false otherwise</returns> /// <exception cref="System.IO.IOException"/> private static bool CheckPermissionOfOther(FileSystem fs, Path path, FsAction action , LoadingCache <Path, Future <FileStatus> > statCache) { FileStatus status = GetFileStatus(fs, path, statCache); FsPermission perms = status.GetPermission(); FsAction otherAction = perms.GetOtherAction(); return(otherAction.Implies(action)); }
/// <exception cref="Org.Apache.Hadoop.Security.AccessControlException"/> public virtual void CheckPermission(string fsOwner, string supergroup, UserGroupInformation ugi, INodeAttributes[] inodeAttrs, INode[] inodes, byte[][] pathByNameArr, int snapshotId, string path, int ancestorIndex, bool doCheckOwner, FsAction ancestorAccess , FsAction parentAccess, FsAction access, FsAction subAccess, bool ignoreEmptyDir ) { Called.AddItem("checkPermission|" + ancestorAccess + "|" + parentAccess + "|" + access ); }
/// <summary>Calculates mask entries required for the ACL.</summary> /// <remarks> /// Calculates mask entries required for the ACL. Mask calculation is performed /// separately for each scope: access and default. This method is responsible /// for handling the following cases of mask calculation: /// 1. Throws an exception if the caller attempts to remove the mask entry of an /// existing ACL that requires it. If the ACL has any named entries, then a /// mask entry is required. /// 2. If the caller supplied a mask in the ACL spec, use it. /// 3. If the caller did not supply a mask, but there are ACL entry changes in /// this scope, then automatically calculate a new mask. The permissions of /// the new mask are the union of the permissions on the group entry and all /// named entries. /// </remarks> /// <param name="aclBuilder">ArrayList<AclEntry> containing entries to build</param> /// <param name="providedMask"> /// EnumMap<AclEntryScope, AclEntry> mapping each scope to /// the mask entry that was provided for that scope (if provided) /// </param> /// <param name="maskDirty"> /// EnumSet<AclEntryScope> which contains a scope if the mask /// entry is dirty (added or deleted) in that scope /// </param> /// <param name="scopeDirty"> /// EnumSet<AclEntryScope> which contains a scope if any entry /// is dirty (added or deleted) in that scope /// </param> /// <exception cref="Org.Apache.Hadoop.Hdfs.Protocol.AclException">if validation fails /// </exception> private static void CalculateMasks(IList <AclEntry> aclBuilder, EnumMap <AclEntryScope , AclEntry> providedMask, EnumSet <AclEntryScope> maskDirty, EnumSet <AclEntryScope > scopeDirty) { EnumSet <AclEntryScope> scopeFound = EnumSet.NoneOf <AclEntryScope>(); EnumMap <AclEntryScope, FsAction> unionPerms = Maps.NewEnumMap <AclEntryScope>(); EnumSet <AclEntryScope> maskNeeded = EnumSet.NoneOf <AclEntryScope>(); // Determine which scopes are present, which scopes need a mask, and the // union of group class permissions in each scope. foreach (AclEntry entry in aclBuilder) { scopeFound.AddItem(entry.GetScope()); if (entry.GetType() == AclEntryType.Group || entry.GetName() != null) { FsAction scopeUnionPerms = Objects.FirstNonNull(unionPerms[entry.GetScope()], FsAction .None); unionPerms[entry.GetScope()] = scopeUnionPerms.Or(entry.GetPermission()); } if (entry.GetName() != null) { maskNeeded.AddItem(entry.GetScope()); } } // Add mask entry if needed in each scope. foreach (AclEntryScope scope in scopeFound) { if (!providedMask.Contains(scope) && maskNeeded.Contains(scope) && maskDirty.Contains (scope)) { // Caller explicitly removed mask entry, but it's required. throw new AclException("Invalid ACL: mask is required and cannot be deleted."); } else { if (providedMask.Contains(scope) && (!scopeDirty.Contains(scope) || maskDirty.Contains (scope))) { // Caller explicitly provided new mask, or we are preserving the existing // mask in an unchanged scope. aclBuilder.AddItem(providedMask[scope]); } else { if (maskNeeded.Contains(scope) || providedMask.Contains(scope)) { // Otherwise, if there are maskable entries present, or the ACL // previously had a mask, then recalculate a mask automatically. aclBuilder.AddItem(new AclEntry.Builder().SetScope(scope).SetType(AclEntryType.Mask ).SetPermission(unionPerms[scope]).Build()); } } } } }
/// <summary> /// Checks for a given path whether the Other permissions on it /// imply the permission in the passed FsAction /// </summary> /// <param name="fs"/> /// <param name="path"/> /// <param name="action"/> /// <returns>true if the path in the uri is visible to all, false otherwise</returns> /// <exception cref="System.IO.IOException"/> private static bool CheckPermissionOfOther(FileSystem fs, Path path, FsAction action , IDictionary <URI, FileStatus> statCache) { FileStatus status = GetFileStatus(fs, path.ToUri(), statCache); FsPermission perms = status.GetPermission(); FsAction otherAction = perms.GetOtherAction(); if (otherAction.Implies(action)) { return(true); } return(false); }
/// <exception cref="Org.Apache.Hadoop.Security.AccessControlException"/> private void Check(INodeAttributes inode, string path, FsAction access) { if (inode == null) { return; } FsPermission mode = inode.GetFsPermission(); AclFeature aclFeature = inode.GetAclFeature(); if (aclFeature != null) { // It's possible that the inode has a default ACL but no access ACL. int firstEntry = aclFeature.GetEntryAt(0); if (AclEntryStatusFormat.GetScope(firstEntry) == AclEntryScope.Access) { CheckAccessAcl(inode, path, access, mode, aclFeature); return; } } if (GetUser().Equals(inode.GetUserName())) { //user class if (mode.GetUserAction().Implies(access)) { return; } } else { if (GetGroups().Contains(inode.GetGroupName())) { //group class if (mode.GetGroupAction().Implies(access)) { return; } } else { //other class if (mode.GetOtherAction().Implies(access)) { return; } } } throw new AccessControlException(ToAccessControlString(inode, path, access, mode) ); }
private FsAction GetFsAction(int accessGroup, FTPFile ftpFile) { FsAction action = FsAction.None; if (ftpFile.HasPermission(accessGroup, FTPFile.ReadPermission)) { action.Or(FsAction.Read); } if (ftpFile.HasPermission(accessGroup, FTPFile.WritePermission)) { action.Or(FsAction.Write); } if (ftpFile.HasPermission(accessGroup, FTPFile.ExecutePermission)) { action.Or(FsAction.Execute); } return(action); }
/// <exception cref="System.IO.IOException"/> private void AssertPermissionDenied(UserGroupInformation user, string path, FsAction access) { try { INodesInPath iip = dir.GetINodesInPath(path, true); dir.GetPermissionChecker(Superuser, Supergroup, user).CheckPermission(iip, false, null, null, access, null, false); NUnit.Framework.Assert.Fail("expected AccessControlException for user + " + user + ", path = " + path + ", access = " + access); } catch (AccessControlException e) { NUnit.Framework.Assert.IsTrue("Permission denied messages must carry the username" , e.Message.Contains(user.GetUserName().ToString())); NUnit.Framework.Assert.IsTrue("Permission denied messages must carry the path parent" , e.Message.Contains(new Path(path).GetParent().ToUri().GetPath())); } }
/// <summary>Prints a single extended ACL entry.</summary> /// <remarks> /// Prints a single extended ACL entry. If the mask restricts the /// permissions of the entry, then also prints the restricted version as the /// effective permissions. The mask applies to all named entries and also /// the unnamed group entry. /// </remarks> /// <param name="aclStatus">AclStatus for the path</param> /// <param name="fsPerm">FsPermission for the path</param> /// <param name="entry">AclEntry extended ACL entry to print</param> private void PrintExtendedAclEntry(AclStatus aclStatus, FsPermission fsPerm, AclEntry entry) { if (entry.GetName() != null || entry.GetType() == AclEntryType.Group) { FsAction entryPerm = entry.GetPermission(); FsAction effectivePerm = aclStatus.GetEffectivePermission(entry, fsPerm); if (entryPerm != effectivePerm) { @out.WriteLine(string.Format("%s\t#effective:%s", entry, effectivePerm.Symbol)); } else { @out.WriteLine(entry); } } else { @out.WriteLine(entry); } }
/// <exception cref="Org.Apache.Hadoop.Security.AccessControlException"/> public virtual void CheckPermission(string fsOwner, string supergroup, UserGroupInformation callerUgi, INodeAttributes[] inodeAttrs, INode[] inodes, byte[][] pathByNameArr , int snapshotId, string path, int ancestorIndex, bool doCheckOwner, FsAction ancestorAccess , FsAction parentAccess, FsAction access, FsAction subAccess, bool ignoreEmptyDir ) { for (; ancestorIndex >= 0 && inodes[ancestorIndex] == null; ancestorIndex--) { } CheckTraverse(inodeAttrs, path, ancestorIndex); INodeAttributes last = inodeAttrs[inodeAttrs.Length - 1]; if (parentAccess != null && parentAccess.Implies(FsAction.Write) && inodeAttrs.Length > 1 && last != null) { CheckStickyBit(inodeAttrs[inodeAttrs.Length - 2], last); } if (ancestorAccess != null && inodeAttrs.Length > 1) { Check(inodeAttrs, path, ancestorIndex, ancestorAccess); } if (parentAccess != null && inodeAttrs.Length > 1) { Check(inodeAttrs, path, inodeAttrs.Length - 2, parentAccess); } if (access != null) { Check(last, path, access); } if (subAccess != null) { INode rawLast = inodes[inodeAttrs.Length - 1]; CheckSubAccess(pathByNameArr, inodeAttrs.Length - 1, rawLast, snapshotId, subAccess , ignoreEmptyDir); } if (doCheckOwner) { CheckOwner(last); } }
/// <exception cref="System.IO.IOException"/> private static bool CheckPublicPermsForAll(FileSystem fs, FileStatus status, FsAction dir, FsAction file) { FsPermission perms = status.GetPermission(); FsAction otherAction = perms.GetOtherAction(); if (status.IsDirectory()) { if (!otherAction.Implies(dir)) { return(false); } foreach (FileStatus child in fs.ListStatus(status.GetPath())) { if (!CheckPublicPermsForAll(fs, child, dir, file)) { return(false); } } return(true); } return(otherAction.Implies(file)); }
/// <exception cref="Org.Apache.Hadoop.Security.AccessControlException"/> /// <exception cref="System.IO.FileNotFoundException"/> /// <exception cref="Org.Apache.Hadoop.FS.UnresolvedLinkException"/> /// <exception cref="System.IO.IOException"/> public override void Access(Path path, FsAction mode) { CheckPath(path); myFs.Access(path, mode); }
/// <exception cref="Org.Apache.Hadoop.Security.AccessControlException"/> /// <exception cref="System.IO.FileNotFoundException"/> /// <exception cref="System.IO.IOException"/> public override void Access(Path path, FsAction mode) { InodeTree.ResolveResult <FileSystem> res = fsState.Resolve(GetUriPath(path), true); res.targetFileSystem.Access(res.remainingPath, mode); }
/// <summary>Checks requested access against an Access Control List.</summary> /// <remarks> /// Checks requested access against an Access Control List. This method relies /// on finding the ACL data in the relevant portions of /// <see cref="Org.Apache.Hadoop.FS.Permission.FsPermission"/> /// and /// <see cref="AclFeature"/> /// as implemented in the logic of /// <see cref="AclStorage"/> /// . This /// method also relies on receiving the ACL entries in sorted order. This is /// assumed to be true, because the ACL modification methods in /// <see cref="AclTransformation"/> /// sort the resulting entries. /// More specifically, this method depends on these invariants in an ACL: /// - The list must be sorted. /// - Each entry in the list must be unique by scope + type + name. /// - There is exactly one each of the unnamed user/group/other entries. /// - The mask entry must not have a name. /// - The other entry must not have a name. /// - Default entries may be present, but they are ignored during enforcement. /// </remarks> /// <param name="inode">INodeAttributes accessed inode</param> /// <param name="snapshotId">int snapshot ID</param> /// <param name="access">FsAction requested permission</param> /// <param name="mode">FsPermission mode from inode</param> /// <param name="aclFeature">AclFeature of inode</param> /// <exception cref="Org.Apache.Hadoop.Security.AccessControlException">if the ACL denies permission /// </exception> private void CheckAccessAcl(INodeAttributes inode, string path, FsAction access, FsPermission mode, AclFeature aclFeature) { bool foundMatch = false; // Use owner entry from permission bits if user is owner. if (GetUser().Equals(inode.GetUserName())) { if (mode.GetUserAction().Implies(access)) { return; } foundMatch = true; } // Check named user and group entries if user was not denied by owner entry. if (!foundMatch) { for (int pos = 0; pos < aclFeature.GetEntriesSize(); pos++) { entry = aclFeature.GetEntryAt(pos); if (AclEntryStatusFormat.GetScope(entry) == AclEntryScope.Default) { break; } AclEntryType type = AclEntryStatusFormat.GetType(entry); string name = AclEntryStatusFormat.GetName(entry); if (type == AclEntryType.User) { // Use named user entry with mask from permission bits applied if user // matches name. if (GetUser().Equals(name)) { FsAction masked = AclEntryStatusFormat.GetPermission(entry).And(mode.GetGroupAction ()); if (masked.Implies(access)) { return; } foundMatch = true; break; } } else { if (type == AclEntryType.Group) { // Use group entry (unnamed or named) with mask from permission bits // applied if user is a member and entry grants access. If user is a // member of multiple groups that have entries that grant access, then // it doesn't matter which is chosen, so exit early after first match. string group = name == null?inode.GetGroupName() : name; if (GetGroups().Contains(group)) { FsAction masked = AclEntryStatusFormat.GetPermission(entry).And(mode.GetGroupAction ()); if (masked.Implies(access)) { return; } foundMatch = true; } } } } } // Use other entry if user was not denied by an earlier match. if (!foundMatch && mode.GetOtherAction().Implies(access)) { return; } throw new AccessControlException(ToAccessControlString(inode, path, access, mode) ); }
/// <summary> /// Guarded by /// <see cref="FSNamesystem.ReadLock()"/> /// /// </summary> /// <exception cref="Org.Apache.Hadoop.Security.AccessControlException"/> private void Check(INodeAttributes[] inodes, string path, int i, FsAction access) { Check(i >= 0 ? inodes[i] : null, path, access); }
/// <exception cref="System.IO.IOException"/> public override void Access(Path path, FsAction mode) { dfs.CheckAccess(GetUriPath(path), mode); }
/// <summary>Constructor.</summary> /// <param name="value">the parameter value.</param> public FsActionParam(FsAction value) : base(Domain, value == null ? null : value.Symbol) { }
/// <summary>Create a new AclEntry with scope, type, name and permission.</summary> /// <param name="scope">AclEntryScope scope of the ACL entry</param> /// <param name="type">AclEntryType ACL entry type</param> /// <param name="name">String optional ACL entry name</param> /// <param name="permission">FsAction set of permissions in the ACL entry</param> /// <returns>AclEntry new AclEntry</returns> public static Org.Apache.Hadoop.FS.Permission.AclEntry AclEntry(AclEntryScope scope , AclEntryType type, string name, FsAction permission) { return(new AclEntry.Builder().SetScope(scope).SetType(type).SetName(name).SetPermission (permission).Build()); }
/// <exception cref="Org.Apache.Hadoop.Security.AccessControlException"/> /// <exception cref="System.IO.FileNotFoundException"/> /// <exception cref="System.IO.IOException"/> public override void Access(Path path, FsAction mode) { fs.Access(path, mode); }
/// <exception cref="Org.Apache.Hadoop.Security.AccessControlException"/> /// <exception cref="System.IO.FileNotFoundException"/> /// <exception cref="System.IO.IOException"/> public override void Access(Path path, FsAction mode) { base.Access(FullPath(path), mode); }
/// <returns> /// a string for throwing /// <see cref="Org.Apache.Hadoop.Security.AccessControlException"/> /// /// </returns> private string ToAccessControlString(INodeAttributes inodeAttrib, string path, FsAction access, FsPermission mode) { return(ToAccessControlString(inodeAttrib, path, access, mode, false)); }
/// <returns> /// a string for throwing /// <see cref="Org.Apache.Hadoop.Security.AccessControlException"/> /// /// </returns> private string ToAccessControlString(INodeAttributes inodeAttrib, string path, FsAction access, FsPermission mode, bool deniedFromAcl) { StringBuilder sb = new StringBuilder("Permission denied: ").Append("user="******", ").Append("access=").Append(access).Append(", ").Append("inode=\"" ).Append(path).Append("\":").Append(inodeAttrib.GetUserName()).Append(':').Append (inodeAttrib.GetGroupName()).Append(':').Append(inodeAttrib.IsDirectory() ? 'd' : '-').Append(mode); if (deniedFromAcl) { sb.Append("+"); } return(sb.ToString()); }