0

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
Community
  • 1
  • 1
ElektroStudios
  • 19,105
  • 33
  • 200
  • 417
  • 1
    have you seen http://stackoverflow.com/q/1281620/1070452 ? – Ňɏssa Pøngjǣrdenlarp Nov 12 '15 at 17:55
  • @Plutonix Thankyou, I'm currentlly seeying those answers. Richard's answer checks for both an "allowed" rule and a "denied" rule, but he doesn't explains why, why there is an allow rule and a deny rule for the same user-right?. I don't want to assume things by myself, need some clarifications. – ElektroStudios Nov 12 '15 at 18:00
  • 1
    There are also some resources (links) sprinkled [on this one](http://stackoverflow.com/q/1281620/1070452) – Ňɏssa Pøngjǣrdenlarp Nov 12 '15 at 18:02
  • 2
    @ElektroStudios Did you read the other answers? Especially [this](http://stackoverflow.com/a/22020271/1842065): *"Deny takes precedence over Allow. Local rules take precedence over inherited rules."* – Bjørn-Roger Kringsjå Nov 12 '15 at 18:10
  • @Bjørn-Roger Kringsjå Yes, thankyou, but I still have problems with that function, it don't works as expected. I updated my queston. – ElektroStudios Nov 12 '15 at 18:38
  • For multiple permissions, can't you just check them individually: `DirectoryHasRights("C:\Test Folder\", FileSystemRights.Read, AccessControlType.Allow) AndAlso DirectoryHasRights("C:\Test Folder\", FileSystemRights.Write, AccessControlType.Allow)`? – Mark Nov 12 '15 at 20:15

0 Answers0