SHARE_INFO_502 Structure and using shi502_security_descriptor

Locked SHARE_INFO_502 Structure and using shi502_security_descriptor

  • sexta-feira, 2 de março de 2012 22:06
     
     

    This is for VB.Net using Visual Studio 2010.  To keep things simple, I'm just targeting .Net v2 for now.  I'm posting here because I believe it's strictly an issue of managed platform invoke marshalling.  I'm trying to use NetShareEnum to report and manipulate share permissions.  I can get NetShareEnum() to work fine.  I can extract the individual shares into structures.  However, I've been unable to use the shi502_security_descriptor pointer member of a SHARE_INFO_502 structure.

    For example, I'd like to use GetSecurityDescriptorDacl() to get the share's Dacl.  I've even managed to do this fine in C++ but I can't seem to make the leap to managed code.  I can find examples for creating new Security Descriptors but none for taking a pointer member of a structure and using it with other api's.

    Can anyone give me a working example to take the shi502_security_descriptor pointer (of type System.IntPtr) and actually use it with the advapi32.dll security functions, such as GetSecurityDescriptorDacl() or GetExplicitEntriesFromAcl()?  Please include your DllImportAttribute declarations.  Thanks!

Todas as Respostas

  • sábado, 3 de março de 2012 17:32
     
     Respondido Contém Código

    Hi,

    in the following excerpt, 'Item' is the starting point of type SHARE_INFO_502. Maybe you don't have all functions (residing in my own libraries), but the relevant declarations are below:

                Dim pSecdesc = item.security_descriptor
    
                If pSecdesc <> IntPtr.Zero Then
                   Dim DaclPresent, DaclDefaulted As Boolean
                   Dim dacl As IntPtr
    
                   If Functions.GetSecurityDescriptorDacl(pSecdesc, DaclPresent, dacl, DaclDefaulted) Then
                      Dim count As UInteger
                      Dim ListStartPtr, CurrentPtr As IntPtr
                      Dim Type = GetType(EXPLICIT_ACCESS)
                      Dim structSize = Marshal.SizeOf(Type)
    
                      If Functions.GetExplicitEntriesFromAcl(dacl, count, ListStartPtr) = Errors.Success Then
                         Try
                            CurrentPtr = ListStartPtr
    
                            Debug.Print("Acl:")
                            Debug.Indent()
    
                            For i = 1UI To count
                               Dim record As EXPLICIT_ACCESS
    
                               Debug.Print("#" & i & ":")
                               Debug.Indent()
    
                               record = DirectCast(Marshal.PtrToStructure(CurrentPtr, Type), EXPLICIT_ACCESS)
    
                               Debug.Print("Accessmode = " & record.AccessMode.ToString)
                               Debug.Print("AccessPermissions = " & record.AccessPermissions.ToString)
                               Debug.Print("Inheritance = " & record.Inheritance.ToString)
                               Debug.Print("Trustee:")
    
                               Debug.Indent()
    
                               If record.Trustee.TrusteeForm = TrusteeForm.IsSid Then
                                  Dim sidString = Helper.ConvertSidToStringSid(record.Trustee.Name)
    
                                  Debug.Print("Name (SID) = " & sidString)
                               Else
                                  Debug.Print("Name = " & record.Trustee.Name.ToString)
                               End If
    
                               Debug.Print("MultipleTrusteeOperation = " & record.Trustee.MultipleTrusteeOperation.ToString)
                               Debug.Print("TrusteeForm = " & record.Trustee.TrusteeForm.ToString)
                               Debug.Print("TrusteeType = " & record.Trustee.TrusteeType.ToString)
                               Debug.Unindent()
    
                               Debug.Unindent()
    
                               CurrentPtr = AddPointer(CurrentPtr, structSize)
                            Next
    
                            Debug.Unindent()
                         Finally
                            Helper.LocalFree(ListStartPtr)
                         End Try
                      Else
                         Helper.ThrowWin32Exception("GetExplicitEntriesFromAcl")
                      End If
                   Else
                      Helper.ThrowWin32Exception("GetSecurityDescriptorDacl")
                   End If
    
    
                End If
    



    Declarations:

       Public Declare Function GetSecurityDescriptorDacl Lib "Advapi32.dll" ( _
          ByVal SecurityDescriptor As IntPtr, _
          ByRef DaclPresent As Boolean, _
          ByRef Dacl As IntPtr, _
          ByRef DaclDefaulted As Boolean) As Boolean
    
       Public Declare Auto Function GetExplicitEntriesFromAcl Lib "Advapi32.dll" ( _
          ByVal ACL As IntPtr, _
          ByRef CountOfExplicitEntries As UInt32, _
          ByRef ListOfExplicitEntries As IntPtr) As UInt32
    
    <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
    Public Structure EXPLICIT_ACCESS
       Public AccessPermissions As AccessMask
       Public AccessMode As AccessMode
       Public Inheritance As UInt32
       Public Trustee As TRUSTEE
    End Structure
    <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
    Public Structure TRUSTEE
       Public MultipleTrustee As IntPtr
       Public MultipleTrusteeOperation As MultipleTrusteeOperation
       Public TrusteeForm As TrusteeForm
       Public TrusteeType As TrusteeType
       Public Name As IntPtr
    End Structure
    Public Enum MultipleTrusteeOperation
       NoMultipleTrustee
       TrusteeIsImpersonate
    End Enum
    
    
    Public Enum TrusteeForm
       IsSid
       IsName
       BadForm
       IsObjectsAndSid
       IsObjectsAndName
    End Enum
    
    
    Public Enum TrusteeType
       IsUnknown
       IsUser
       IsGroup
       IsDomain
       IsAlias
       IsWellKnownGroup
       IsDeleted
       IsInvalid
       IsComputer
    End Enum

    Let me know if declarations are missing.


    Armin

  • quinta-feira, 8 de março de 2012 16:28
    Moderador
     
     

    Hi Bcmem,

    Welcome to the MSDN Forum.

    How about Armin's suggestion? Does it work for you?

    @Armin,

    Thank you for contrubuting on this forum.

    Have a nice day.

    Best regards,


    Mike Feng
    MSDN Community Support | Feedback to us
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

  • quinta-feira, 8 de março de 2012 16:44
     
     

    Armin,

    Thanks for the thorough help.  My basic problem was incorrect ByRef and ByVal choices.  I can now get the ACL's using GetExplicitEntriesFromAcl().  The actual object is a Windows share and the returned trustees are SID's, not names.  So I declared the Trustee structure with Name as IntPtr.  I can't get past ConvertSidToString.  Debugging looks good up to that step.  bResult is returning 2 (the number of ACL's) so there is no error.  However, the conversion does not give me a valid string.  Since the string is LPTSTR *StringSid, I declared it as ByRef IntPtr so I can free it later using LocalFree().  Can you share your Helper code for calling Convert or is there something wrong?  Thanks again!  Here are my relevant code snippits:

    <StructLayoutAttribute(LayoutKind.Sequential)> _
        Private Structure EXPLICIT_ACCESS
            Public grfAccessPermissions As UInteger
            Public grfAccessMode As ACCESS_MODE
            Public grfInheritance As UInteger
            Public Trustee As TRUSTEE
        End Structure

        <StructLayoutAttribute(LayoutKind.Sequential)> _
        Private Structure TRUSTEE
            Public pMultipleTrustee As UInteger
            Public MultipleTrusteeOperation As MULTIPLE_TRUSTEE_OPERATION
            Public TrusteeForm As TRUSTEE_FORM
            Public TrusteeType As TRUSTEE_TYPE
            Public Name As System.IntPtr
        End Structure

    <DllImportAttribute("advapi32.dll", entrypoint:="GetExplicitEntriesFromAcl")> _
        Private Shared Function GetExplicitEntriesFromAcl(<InAttribute()> ByVal pacl As IntPtr, <OutAttribute()> ByRef pCountOfExplicitEntries As UInteger, <OutAttribute()> ByRef pListOfExplicitEntries As System.IntPtr) As UInteger
        End Function

    <DllImportAttribute("advapi32.dll", EntryPoint:="ConvertSidToStringSid")> _
        Private Shared Function ConvertSidToStringSid(<InAttribute()> ByVal Sid As System.IntPtr, <OutAttribute()> ByRef StringSid As System.IntPtr) As System.Int32
        End Function

    Dim pDacl As System.IntPtr

    bResult = GetSecurityDescriptorDacl(PsecDesc, bDaclPresent, pDacl, bDaclDefaulted)

    Dim pcCountOfExplicitEntries As UInteger

    Dim pListOfExplicitEntries As System.IntPtr

    Result = GetExplicitEntriesFromAcl(pDacl, pcCountOfExplicitEntries, pListOfExplicitEntries)

    Dim ExplicitEntries(pcCountOfExplicitEntries - 1) As EXPLICIT_ACCESS

    For j = 0 To pcCountOfExplicitEntries - 1

     ExplicitEntries(j) = Marshal.PtrToStructure( _
               CType(pListOfExplicitEntries.ToInt32 + Marshal.SizeOf(GetType(EXPLICIT_ACCESS)) * j, IntPtr) _
                                    , GetType(EXPLICIT_ACCESS) _)

     If ExplicitEntries(j).Trustee.TrusteeForm = TRUSTEE_FORM.TRUSTEE_IS_SID Then

      Dim PstrSid As System.IntPtr

      bResult = ConvertSidToStringSid(ExplicitEntries(j).Trustee.Name, PstrSid)

      Dim strSid As String

      strSid = Marshal.PtrToStringAuto(PstrSid)

      Debug.Print(Shares(i).shi502_netname + ": " + strSid)

      LocalFree(PstrSid)

     End If

    Next

  • quinta-feira, 15 de março de 2012 04:55
     
     

    Hi Bcmem,

    Your code isnot debuggerable, This is may be the reason Armin doesn't follow this thread anymore, so would you like to post a debuggerable code snippet here?

    Have a nice day.


    Ghost,
    Call me ghost for short, Thanks
    To get the better anwser, it should be a better question.

  • quinta-feira, 15 de março de 2012 08:25
     
     

    Oh, I'm sorry, somehow I've overlooked this thread. It was not because the code is not compilable, though you're right, Ghost, it's not compilable even if I add missing declarations. Inappropriate data type handling is not good for a programmer. :) 

    bcmem, please add Option Strict On at the top of the file and do the necessary corrections. If you post again, the thread will become "unread" and I will (try to) respond.


    Armin

  • quinta-feira, 15 de março de 2012 09:07
     
      Contém Código

    Again sorry for not replying. Helper.ConvertSidToStringSid is nothing special, but here it is:

       Public Shared Function ConvertSidToStringSid(ByVal sid As IntPtr) As String
    
          Dim bufferPtr As IntPtr
    
          If Functions.ConvertSidToStringSid(sid, bufferPtr) Then
             Try
                Return Marshal.PtrToStringAuto(bufferPtr)
             Finally
                LocalFree(bufferPtr)
             End Try
          Else
             ThrowWin32Exception("ConvertSidToStringSid")
          End If
    
       End Function

    Our declarations of ConvertSidToStringSid match, so I don't post mine. EDIT: This statement turned to be out wrong, later.

    The only noticable thing I see - but I don't think it's the problem - is that you're using pListOfExplicitEntries.ToInt32. This would fail on a 64 bit machine, or at least it's not safe. You may change that later. I wanted to post my AddPointer function at this point, but it again references own libraries.

    I guess 'i' in "Shares(i).shi502_netname" is the loop variable for the enclosing loop.

    You shouldn't ignore the return value or GetExplicitEntriesFromAcl.


    Ok, I've pieced together working code keeping yours and added mine. Current state: There's a problem in the line

     ExplicitEntries(j) = Marshal.PtrToStructure( _
               CType(pListOfExplicitEntries.ToInt32 + Marshal.SizeOf(GetType(EXPLICIT_ACCESS)) * j, IntPtr) _
                                    , GetType(EXPLICIT_ACCESS) _)

    because I get a different result than in my original posted coded. I'm looking at it now and will report again.....


    Armin


    • Editado Armin Zingler quinta-feira, 15 de março de 2012 09:32
    •  
  • quinta-feira, 15 de março de 2012 09:31
     
     Respondido Contém Código

    Solution:

    Your declaration of

       Public pMultipleTrustee As UInteger

    in structure Trustee is wrong. Must be IntPtr, not UInteger. Not what I posted. ;)

    In addition, the Auto charset is missing in your declaration of ConvertSidToStringSid. That's why the ANSI version is used instead of Unicode, so the correct version is:

       Public Declare Auto Function ConvertSidToStringSid Lib "Advapi32.dll" ( _
          ByVal SID As IntPtr, _
          ByRef StringSid As IntPtr) As Boolean
    

    Getting back an ANSI String called with Marshal.PtrToStringAuto doesn't match because the latter expects Unicode.

    Should work now.


    Armin

  • quinta-feira, 15 de março de 2012 13:24
     
     

    Armin,

    Thanks so much for your time and help.  It was indeed the string charset; I can't believe how much time I wasted on this issue.  I didn't include "Charset:=" because it appeared my program default was Unicode so I thought the Unicode version would be automatically chosen.  I guess that's the case in C++ when you include the real SDK headers but not for VB.Net.  I may be back to the forums as I progress but I've learned a lot troubleshooting this issue.  Thanks again.

  • quinta-feira, 15 de março de 2012 13:25
     
     
    Thanks for the tip.
  • quinta-feira, 15 de março de 2012 13:28
     
     
    Thanks for the code post and I'll keep the 64-bit in mind.  I was aware that my code might not work on 64-bit but is less of a priority right now.  I only use 32-bit workstations for development at the moment.  Also, I assume (but could be wrong) that since I'm targeting 32-bit on compilation, 64-bit Windows would run it as 32-bit.  Thanks.