Re: Checking "Reset Password" Extended Attribute in AD

From: Joe Richards [MVP] (humorexpress_at_hotmail.com)
Date: 10/16/04

  • Next message: Dave Mills: "Re: Checking "Reset Password" Extended Attribute in AD"
    Date: Sat, 16 Oct 2004 11:02:45 -0400
    
    

    I haven't ever used this function so I am just guessing. BTW, I looked through
    the MSDN docs, they pretty much suck for these functions, they need some
    examples. Oh, I also don't do NET but tried to work through what you are doing
    anyway...

    First off

    > Dim gUSER As New Guid("bf967aba-0de6-11d0-a285-00aa00000000")
    > '00aa003049e2
    >

    I expect so, but do you know that GUID isn't correct, the part you remmed out
    top replace with 0's is correct.

    dn:CN=User,CN=Schema,CN=Configuration,DC=joe,DC=com
    >schemaIDGUID: {BF967ABA-0DE6-11D0-A285-00AA003049E2}

    Other than that what I would try in your shoes is to not put the Reset Password
    GUID into the property level of OBJECT_TYPE_LIST, I would put it into the
    property set level. It isn't a property, it is a special CA access right which
    is closer to being a property set than a property. In fact it is maintained in
    with the property sets.

    Now I am going to see if I contact someone on how "light" those docs are on MSDN.

       joe

    --
    Joe Richards Microsoft MVP Windows Server Directory Services
    www.joeware.net
    Dave Mills wrote:
    > I'm writing a web page which certain users will be able to use to reset 
    > student passwords, without needing the "Users and Computers" MMC page.
    > 
    > I need to be able to check if the user which IIS is currently 
    > impersonating has the right to reset a given user's password - my 
    > instinct told me to go with the "AccessCheckByType" API function - I 
    > have managed to get the impersonated user's token, and the security 
    > descriptor from the User in active directory - I call AccessCheckByType 
    > and it returns success however it is not returning the correct results 
    > in status.
    > 
    > Am I even correct in thinking AccessCheckByType is the correct function 
    > to use??
    > 
    > Cheers
    > 
    > Dave
    > 
    > Code below:
    > 
    > Dim result As Integer 'for return codes!!#
    > Dim lasterror As Integer
    > 
    > Dim deCurriculum As New 
    > DirectoryServices.DirectoryEntry("LDAP://student.spacollege.ac.uk", 
    > "student\Administrator", "monkey") 'where you want to look for the 
    > account
    > Dim obj As Object = deCurriculum.NativeObject
    > Dim dsSrch As New DirectorySearcher(deCurriculum)
    > Dim strUsername As String = txtUsername.Text
    > dsSrch.Filter = "(&(objectClass=user)(sAMAccountName=" & strUsername & 
    > "))"
    > 
    > Dim srUser As SearchResult = dsSrch.FindOne()
    > If srUser Is Nothing Then Throw New Exception("UserNotFound")
    > Dim deUser As DirectoryEntry = srUser.GetDirectoryEntry()
    > 
    > 'get some user details
    > lblUsername.Text = CType(deUser.Properties("sAMAccountName").Value, 
    > String)
    > lblFirstName.Text = CType(deUser.Properties("givenName").Value, String)
    > lblSurname.Text = CType(deUser.Properties("sn").Value, String)
    > 
    > '---------------------------------------------------------------------------------------------------------------------------------'
    > 'Setup SID
    > 
    > 'Get SID from DirectoryEntry
    > Dim bytearraySID() As Byte = deUser.Properties("objectSid").Value()
    > Dim pSID As IntPtr = Marshal.AllocHGlobal(bytearraySID.Length)
    > Marshal.Copy(bytearraySID, 0, pSID, bytearraySID.Length)
    > result = IsValidSid(pSID) 'check SID is valid (sanity check!)
    > 
    > '---------------------------------------------------------------------------------------------------------------------------------'
    > 'Get the binary security descriptor from deUser
    > 
    > 'force the property into the property cache
    > Dim aProperties() = {"NTSecurityDescriptor"}
    > deUser.Invoke("GetInfoEx", New Object() {aProperties, 0})
    > 
    > Dim pv2SecDesc As ActiveDs.IADsPropertyValue2 = 
    > deUser.Invoke("GetPropertyItem", New Object() {"NTSecurityDescriptor", 
    > 26}).Values(0)
    > Dim bytearraySecDesc() As Byte = pv2SecDesc.GetObjectProperty(8) '8 = as 
    > byte array
    > 'Dim sdSecDesc As ActiveDs.IADsSecurityDescriptor = 
    > pv2SecDesc.GetObjectProperty(26)
    > Dim pSelfRelativeSecDesc As IntPtr = 
    > Marshal.AllocHGlobal(bytearraySecDesc.Length)
    > 'copy security descriptor to memory location
    > Marshal.Copy(bytearraySecDesc, 0, pSelfRelativeSecDesc, 
    > bytearraySecDesc.Length)
    > 
    > 'setup some variables for conversion from self-relative to absolute 
    > format
    > Dim AbsoluteSecDesc As SECURITY_DESCRIPTOR
    > Dim dwAbsoluteSecDescSize As Integer
    > Dim pDacl As IntPtr
    > Dim dwDaclSize As Integer
    > Dim pSacl As IntPtr
    > Dim dwSaclSize As Integer
    > Dim pOwner As IntPtr
    > Dim dwOwnerSize As Integer
    > Dim pPrimaryGroup As IntPtr
    > Dim dwPrimaryGroupSize As Integer
    > 
    > dwAbsoluteSecDescSize = Marshal.SizeOf(AbsoluteSecDesc)
    > 'find out the sizes of the memory to allocate
    > MakeAbsoluteSD(pSelfRelativeSecDesc, AbsoluteSecDesc, 
    > dwAbsoluteSecDescSize, pDacl, dwDaclSize, pSacl, dwSaclSize, _
    >     pOwner, dwOwnerSize, pPrimaryGroup, dwPrimaryGroupSize)
    > pDacl = Marshal.AllocHGlobal(dwDaclSize)
    > pSacl = Marshal.AllocHGlobal(dwSaclSize)
    > pOwner = Marshal.AllocHGlobal(dwOwnerSize)
    > pPrimaryGroup = Marshal.AllocHGlobal(dwPrimaryGroupSize)
    > 'convert self-relative security descriptor to absolute format
    > MakeAbsoluteSD(pSelfRelativeSecDesc, AbsoluteSecDesc, 
    > dwAbsoluteSecDescSize, pDacl, dwDaclSize, pSacl, dwSaclSize, _
    >     pOwner, dwOwnerSize, pPrimaryGroup, dwPrimaryGroupSize)
    > 'deallocate as not needed any more
    > Marshal.FreeHGlobal(pSelfRelativeSecDesc)
    > 
    > result = IsValidSecurityDescriptor(AbsoluteSecDesc) 'check absolute 
    > security descriptor is valid (sanity check!)
    > 
    > '---------------------------------------------------------------------------------------------------------------------------------'
    > 'Get Impersonated User's token
    > 
    > 'ImpersonateSelf(SecurityImpersonation) 'not needed as IIS is already 
    > impersonating authenticated user
    > 
    > Dim strImpersonatedUser As String = 
    > System.Threading.Thread.CurrentPrincipal.Identity.Name 'just out of 
    > interest!!
    > 
    > Dim token As Integer
    > result = OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, False, token)
    > 
    > '---------------------------------------------------------------------------------------------------------------------------------'
    > 'Setup OBJECT_TYPE_LIST array
    > 
    > 'Setup GUIDs
    > Dim gRESETPASSWORD As New Guid("00299570-246d-11d0-a768-00aa006e0529")
    > Dim pResetPasswordGuid As IntPtr = 
    > Marshal.AllocHGlobal(gRESETPASSWORD.ToByteArray().Length)
    > Marshal.Copy(gRESETPASSWORD.ToByteArray(), 0, pResetPasswordGuid, 
    > gRESETPASSWORD.ToByteArray().Length)
    > 
    > Dim gUSER As New Guid("bf967aba-0de6-11d0-a285-00aa00000000") 
    > '00aa003049e2
    > Dim pUserGuid As IntPtr = 
    > Marshal.AllocHGlobal(gUSER.ToByteArray().Length)
    > Marshal.Copy(gUSER.ToByteArray(), 0, pUserGuid, 
    > gUSER.ToByteArray().Length)
    > 
    > Dim gNULL As New Guid
    > Dim pNullGuid As IntPtr = 
    > Marshal.AllocHGlobal(gNULL.ToByteArray().Length)
    > Marshal.Copy(gNULL.ToByteArray(), 0, pNullGuid, 
    > gNULL.ToByteArray().Length)
    > 
    > Dim ObjectTypeList(0) As OBJECT_TYPE_LIST
    > Dim ObjectTypeListLength As Integer = 0
    > 
    > ObjectTypeList(0).Level = 0
    > ObjectTypeList(0).Sbz = 0
    > ObjectTypeList(0).ObjectType = pUserGuid
    > 
    > 'ObjectTypeList(1).Level = 1
    > 'ObjectTypeList(1).Sbz = 0
    > 'ObjectTypeList(1).ObjectType = pNullGuid
    > 
    > 'ObjectTypeList(2).Level = 2
    > 'ObjectTypeList(2).Sbz = 0
    > 'ObjectTypeList(2).ObjectType = pResetPasswordGuid
    > 
    > '---------------------------------------------------------------------------------------------------------------------------------'
    > 'Check extended right
    > 
    > Dim DesiredAccess As Integer = ADS_RIGHT_DS_CONTROL_ACCESS
    > 
    > Dim GenMap As GENERIC_MAPPING
    > GenMap.GenericRead = 0
    > GenMap.GenericWrite = 0
    > GenMap.GenericExecute = 0
    > GenMap.GenericAll = 0
    > MapGenericMask(DesiredAccess, GenMap)
    > 
    > Dim pPrivilegeSet As IntPtr = IntPtr.Zero
    > Dim PrivilegeSetLength As Integer = 0
    > 
    > Dim GrantedAccess As Integer
    > Dim Status As Integer
    > 
    > 'calculate size of PriviledgeSet
    > result = AccessCheckByType(AbsoluteSecDesc, pSID, token, DesiredAccess, 
    > ObjectTypeList, ObjectTypeListLength, _
    >     GenMap, pPrivilegeSet, PrivilegeSetLength, GrantedAccess, Status)
    > pPrivilegeSet = Marshal.AllocHGlobal(PrivilegeSetLength)
    > 'Check Access
    > result = AccessCheckByType(AbsoluteSecDesc, pSID, token, DesiredAccess, 
    > ObjectTypeList, ObjectTypeListLength, _
    >     GenMap, pPrivilegeSet, PrivilegeSetLength, GrantedAccess, Status)
    > lasterror = Err.LastDllError
    > 
    > '---------------------------------------------------------------------------------------------------------------------------------'
    > 'DeAllocate memory - todo integrate with exception handling
    > 
    > Marshal.FreeHGlobal(pDacl)
    > Marshal.FreeHGlobal(pSacl)
    > Marshal.FreeHGlobal(pOwner)
    > Marshal.FreeHGlobal(pPrimaryGroup)
    > 
    > Marshal.FreeHGlobal(pSID)
    > 
    > Marshal.FreeHGlobal(pResetPasswordGuid)
    > Marshal.FreeHGlobal(pUserGuid)
    > Marshal.FreeHGlobal(pNullGuid)
    > 
    > Marshal.FreeHGlobal(pPrivilegeSet)
    > 
    

  • Next message: Dave Mills: "Re: Checking "Reset Password" Extended Attribute in AD"