I'm trying to determine whether a directory has the specified rights with the function below:
Public Function DirectoryHasRights(ByVal directoryPath As String,
ByVal rights As FileSystemRights,
ByVal accessControlType As AccessControlType) As Boolean
Dim dInfo As DirectoryInfo = New DirectoryInfo(directoryPath)
Dim user As WindowsIdentity = WindowsIdentity.GetCurrent
Dim principle As WindowsPrincipal = DirectCast(Thread.CurrentPrincipal, WindowsPrincipal)
Dim acl As AuthorizationRuleCollection =
dInfo.GetAccessControl.GetAccessRules(True, True, GetType(SecurityIdentifier))
For Each rule As FileSystemAccessRule In acl
If user.User.Equals(rule.IdentityReference) Or
principle.IsInRole(DirectCast(rule.IdentityReference, SecurityIdentifier)) Then
If rule.AccessControlType.Equals(accessControlType) Then
If rule.FileSystemRights.HasFlag(rights) Then
Return True
End If
End If
End If
Next
Return False
End Function
Usage example:
Dim hasRights As Boolean =
DirectoryHasRights("C:\Test Folder\",
FileSystemRights.Read Or FileSystemRights.Write,
AccessControlType.Allow)
The problem I have is that I get AccessControlType.Allow
rules and also AccessControlType.Deny
rules for each user-right that I try to check. I mean that for example I set a directory to deny me FullControl, I ensured I can't access the folder, but the For-loop that iterates the rules gets a rule where FullControl is allowed and also another rule where FullControl is denied both for my current user, how is that possible?.
How I can fix the function?.
UPDATE
So I have translated @Olivier Jacot-Descombes solution to Vb.Net and adapted it to check for AccessControlType.Allow
or AccessControlType.Deny
, but the function below does not works as expected.
If I deny the Read user-right to a folder, then I call the function below using multiple flags, I always get True:
DirectoryHasRights("C:\Test Folder\",
FileSystemRights.Read Or FileSystemRights.Write,
AccessControlType.Allow)
It should return False because I cannot read from the folder. Seems that the function is not comparing for multiple flags.
How I can fix it?.
Source-Code
<DebuggerStepThrough>
Public Function DirectoryHasRights(ByVal directoryPath As String,
ByVal rights As FileSystemRights,
ByVal accessControlType As AccessControlType) As Boolean
Dim acl As AuthorizationRuleCollection =
New DirectoryInfo(directoryPath).GetAccessControl().GetAccessRules(True, True, GetType(SecurityIdentifier))
Return InternalHasRights(acl, rights, accessControlType)
End Function
<DebuggerStepThrough>
Private Function InternalHasRights(ByVal acl As AuthorizationRuleCollection,
ByVal rights As FileSystemRights,
ByVal access As AccessControlType) As Boolean
Dim winId As WindowsIdentity = WindowsIdentity.GetCurrent
Dim winPl As New WindowsPrincipal(winId)
Dim allow As Boolean = False
Dim inheritedAllow As Boolean = False
Dim inheritedDeny As Boolean = False
For Each rule As FileSystemAccessRule In acl
' If the current rule applies to the current user then...
If winId.User.Equals(rule.IdentityReference) OrElse
winPl.IsInRole(DirectCast(rule.IdentityReference, SecurityIdentifier)) Then
If (rule.AccessControlType.Equals(accessControlType.Deny)) AndAlso
((rule.FileSystemRights And rights) = rights) Then
If rule.IsInherited Then
inheritedDeny = True
Else
' Non inherited "deny" rule takes overall precedence.
If (access = AccessControlType.Deny) Then
Return True
Else
Return False
End If
End If
ElseIf (rule.AccessControlType.Equals(accessControlType.Allow)) AndAlso
((rule.FileSystemRights And rights) = rights) Then
If rule.IsInherited Then
inheritedAllow = True
Else
allow = True
End If
End If
End If
Next rule
If (allow) AndAlso (access = AccessControlType.Allow) Then
' Non inherited "allow" takes precedence over inherited rules.
Return True
ElseIf (inheritedAllow AndAlso Not inheritedDeny) AndAlso (access = AccessControlType.Allow) Then
Return True
Else
Return (inheritedDeny AndAlso Not inheritedAllow)
End If
End Function