Solved

Error The security ID structure is invalid using VBScript to alter ACE on an address list

Posted on 2007-04-02
11
1,706 Views
Last Modified: 2012-06-21
Hi I have written a script to alter the ACE list in an ACL for Exchange2003 I am programmaticaly trying to set Adrees Book and GAL access.
The problem is I keep getting the error
 The security ID Structure is invalid.
I am not sure how to fix this as far as I was aware Exchange2003 should reorder this for you.
this is the code I am using.


' Define Constants NB we dont want child objects to inherit
Const ADS_ACEFLAG_INHERIT_ACE = &H2
Const ADS_ACEFLAG_NO_PROPAGATE_INHERIT_ACE = &H4 'clears the inherit flag for inherited aces
Const ADS_ACETYPE_ACCESS_ALLOWED_OBJECT = &H5
Const ADS_RIGHT_GENERIC_ALL = &H10000000
Const ADS_ACETYPE_ACCESS_ALLOWED = &H5
Const ADS_ACEFLAG_ACCESS_DENIED = &H1
Const OPEN_ADDRESS_LIST = "{a1990816-4298-11d1-ade2-00c04fd8d5cd}"


' Get the object, security descriptor, and DACL
Set objAD = GetObject("LDAP://cn=Banana AB,cn=All Address Lists,cn=Address List Container,cn=SoHosted001,cn=Microsoft Exchange,cn=Services,cn=Configuration,dc=SOHOSTED001,dc=lan")
Set objSD = objAD.Get("ntSecurityDescriptor")
Set objDACL = objSD.DiscretionaryAcl

' Create the ACE and set its properties first remove authenticated users
Set objACE = CreateObject("AccessControlEntry")
objACE.Trustee = "SOHOSTED001\Authenticated Users"
objACE.AceFlags = ADS_ACEFLAG_NO_PROPAGATE_INHERIT_ACE
objACE.AceType = ADS_ACEFLAG_ACCESS_DENIED
objACE.AceType = ADS_ACETYPE_ACCESS_DENIED_OBJECT
'objACE.AccessMask = ADS_RIGHT_GENERIC_ALL

Set objACE1 = CreateObject("AccessControlEntry")
objACE1.Trustee = "SOHOSTED001\Banana GRP"
objACE1.AceFlags = ADS_ACEFLAG_INHERIT_ACE
objACE1.AceType = ADS_ACETYPE_ACCESS_ALLOWED
objACE1.AccessMask = ADS_RIGHT_READ_CONTROL
objACE1.AccessMask = ADS_RIGHT_DS_LIST_OBJECT
objACE1.AccessMask = ADS_RIGHT_DS_READ_PROP
objACE1.AccessMask = ADS_RIGHT_ACTRL_DS_LIST

Set objACE2 = CreateObject("AccessControlEntry")
objACE2.Trustee = "SOHOSTED001\Banana GRP"
objACE2.AceType = ADS_ACETYPE_ACCESS_ALLOWED_OBJECT
objACE2.AccessMask = ADS_RIGHT_DS_CONTROL_ACCESS
objACE2.AccessMask = ADS_FLAG_OBJECT_TYPE_PRESENT
objACE2.ObjectType = OPEN_ADDRESS_LIST




' Add the ACE to the DACL object
objDACL.AddAce objACE
objDACL.AddAce objACE1
objDACL.AddAce objACE2
' Write the DACL object back to the security descriptor
objSD.DiscretionaryAcl = objDACL

' Write the security descriptor back to the AD object
objAD.Put "ntSecurityDescriptor", Array(objSD)
objAD.SetInfo

what I want to do is remove Authorised Users and add permissions for a group, in this case Banana GRP
Any advice most welcome
Thanks
0
Comment
Question by:tim_storey
  • 7
  • 4
11 Comments
 
LVL 70

Expert Comment

by:Chris Dent
ID: 18841738

I haven't tested any of this. But I suspect your problem is caused by this:

' Create the ACE and set its properties first remove authenticated users
Set objACE = CreateObject("AccessControlEntry")
objACE.Trustee = "SOHOSTED001\Authenticated Users"
objACE.AceFlags = ADS_ACEFLAG_NO_PROPAGATE_INHERIT_ACE
objACE.AceType = ADS_ACEFLAG_ACCESS_DENIED
objACE.AceType = ADS_ACETYPE_ACCESS_DENIED_OBJECT
'objACE.AccessMask = ADS_RIGHT_GENERIC_ALL

You care creating a new ACE with an explicit Deny rather than removing the entry from the DACL entirely. Is that really what you wanted to do? This entry has the potential (at least) to conflict with the existing ACE for that Trustee.

If you want to remove the ACE you can do so by looping through the DACL:

For Each objACE in objDACL
    If LCase(objACE.Trustee.Name) = LCase("SOHOSTED001\Authenticated Users") Then
        objDACL.RemoveACE objACE
    End If
Next

I might be wrong with objACE.Trustee.Name, it would be worth echoing that out to test it's really the value we're chasing.

You will still have to commit the DACL back to the object after this, or continue to modify the DACL for the other users.

If that fails, try adding your ACE entries one at a time to see if any one of them produces an error.

Chris
0
 
LVL 1

Author Comment

by:tim_storey
ID: 18843924
Thanks Chris,

well I have tried this and found that for one thing I should be using NT Authority as the trustee well if I loop through the ACE's and echo them that's how its listed

So I ran a loop to remove the trustee as you suggested

and I am now getting a type mismatch at the objDACL.AddAce objACE line

I am wondering if this is because I am trying to remove a NT Authority account ?

and I am still getting the security ID structure is invalid if I try adding the other ACE's

any clues?

Tim
0
 
LVL 70

Expert Comment

by:Chris Dent
ID: 18844005

I'd make it one step at a time then. We also need to alter your AccessMasks, I should have noticed that earlier. Access Masks are computed by adding the constant values you're using together. See the modification below.


' Get the object, security descriptor, and DACL
Set objAD = GetObject("LDAP://cn=Banana AB,cn=All Address Lists,cn=Address List Container,cn=SoHosted001,cn=Microsoft Exchange,cn=Services,cn=Configuration,dc=SOHOSTED001,dc=lan")
Set objSD = objAD.Get("ntSecurityDescriptor")
Set objDACL = objSD.DiscretionaryAcl

For Each objACE in objDACL
    If LCase(objACE.Trustee.Name) = LCase("SOHOSTED001\NT Authority") Then
        objDACL.RemoveACE objACE
    End If
Next

' Put it back in to test the changes we're making:

' Write the DACL object back to the security descriptor
objSD.DiscretionaryAcl = objDACL

' Write the security descriptor back to the AD object
objAD.Put "ntSecurityDescriptor", Array(objSD)
objAD.SetInfo

' Request a new copy of the DACL

Set objSD = objAD.Get("ntSecurityDescriptor")
Set objDACL = objSD.DiscretionaryAcl

Set objACE1 = CreateObject("AccessControlEntry")
objACE1.Trustee = "SOHOSTED001\Banana GRP"
objACE1.AceFlags = ADS_ACEFLAG_INHERIT_ACE
objACE1.AceType = ADS_ACETYPE_ACCESS_ALLOWED
objACE1.AccessMask = ADS_RIGHT_READ_CONTROL + ADS_RIGHT_DS_LIST_OBJECT +_
                                     ADS_RIGHT_DS_READ_PROP + ADS_RIGHT_ACTRL_DS_LIST

Set objACE2 = CreateObject("AccessControlEntry")
objACE2.Trustee = "SOHOSTED001\Banana GRP"
objACE2.AceType = ADS_ACETYPE_ACCESS_ALLOWED_OBJECT
objACE2.AccessMask = ADS_RIGHT_DS_CONTROL_ACCESS + ADS_FLAG_OBJECT_TYPE_PRESENT
objACE2.ObjectType = OPEN_ADDRESS_LIST

objDACL.AddAce objACE1
objDACL.AddAce objACE2
' Write the DACL object back to the security descriptor
objSD.DiscretionaryAcl = objDACL

' Write the security descriptor back to the AD object
objAD.Put "ntSecurityDescriptor", Array(objSD)
objAD.SetInfo



Remember that when we did this, we also needed to remove "objDACL.AddAce objACE" because we didn't create that one when we used the looping method to remove the unwanted ACE.

Chris
0
 
LVL 1

Author Comment

by:tim_storey
ID: 18846207
Thanks Chris,

well I am still getting security ID structure is invalid with ACE1 and ACE2 but not with ACE
I am pretty sure that the remove loop is working however this permission is an inherited one.

If I were to remove it manually I would have to disable Inherit in the Advanced permissions.... so this Ace_Flag needs to be set correctly, I think.....

Tim
0
 
LVL 70

Expert Comment

by:Chris Dent
ID: 18847198

Okay, I'll have another look in the morning. I have some sample code for disabling Inheritance I wrote quite a while ago. Although it's File System inheritance, I'll check that as well.

Chris
0
How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

 
LVL 70

Expert Comment

by:Chris Dent
ID: 18849173

Okie dokie, lets try and get to the bottom of this one.

Windows permission structures are complex beasts, there never seems enough documentation to do what you want (or the MSDN links come back with "Content not found").

If this doesn't play you'll have to give me another day to get a test environment setup at home. I haven't got around to installing Exchange there and I'm unwilling to test permission setting on the lists here.

First of all, we need to deal with that Inheritance Flag:


Const SE_DACL_PROTECTED = &H1000

' Get the Object and Security Descriptor

Set objAD = GetObject("LDAP://cn=Banana AB,cn=All Address Lists,cn=Address List Container,cn=SoHosted001,cn=Microsoft Exchange,cn=Services,cn=Configuration,dc=SOHOSTED001,dc=lan")
Set objSD = objAD.Get("ntSecurityDescriptor")

' Disable Inheritance on the Security Descriptor

intControl = objSD.Control
objSD.Control = intControl Or SE_DACL_PROTECTED


That done we must create an entirey new DACL, the parent Address List won't have anything remotely useful now. In order to do that we must copy the DACL from the Parent:


' Get the SD from the Parent

Set objParent = GetObject("LDAP://CN=All Address Lists,CN=Address List Container," &_
      "cn=SoHosted001,cn=Microsoft Exchange,cn=Services,cn=Configuration,dc=SOHOSTED001,dc=lan")
Set objParentSD = objParent.Get("ntSecurityDescriptor")
Set objPatentDACL = objParentSD.DiscretionaryAcl

' Hold a Copy of the Parents DACL in Memory

Set objCopiedDACL = objParentDACL.CopyAccessList()


Okay, now we've got our copy we can modify the ACL so it does what we want:


' Loop through the Copied ACL to remove the unwanted ACE

For Each objACE in objCopiedDACL
      If objACE.Trustee = "NT Authority\Authenticated Users" Then
            objCopiedDACL.RemoveACE objACE
      End If
Next


Now we can add in our new Entries. I think we're going to have to extend the ones used above. I'll continue with that bit in the next post.

Chris
0
 
LVL 70

Accepted Solution

by:
Chris Dent earned 500 total points
ID: 18849315

No we're not, I'm just being blind. Must get more coffee.

MS actually can help us out here though, they have pre-built functions for adding an ACE to a DACL, and another to reorder the DACL (if required). Conveniently all displayed in this article which incorporates what you're doing here:

http://msdn2.microsoft.com/en-us/library/aa123957.aspx

Unfortunately the example of this on MSDN lacks the values for the Masks they're using, without being able to apply them I can't reverse to see what it's built out of. So we have that obscure 256


AddAce objCopiedDACL, "SOHOSTED001\Banana GRP", 131220, 0, 2, 0, 0, 0
AddAce objCopiedDACL, "SOHOSTED001\Banana GRP", 256, 5, 2, 1, OPEN_ADDRESS_LIST, 0


MS also add in a ACE for an Administrator, you may consider doing that as well:


AddAce objCopiedDACL, "SOHOSTED001\<Admin>", 131220, 0, 2, 0, 0, 0
AddAce objCopiedDACL, "SOHOSTED001\<Admin>", 256, 5, 2, 1, OPEN_ADDRESS_LIST, 0


We should also Re-Order the ACE. I don't think we're going to able to avoid it, although you're welcome to try applying the existing DACL back to the SD.


Set objDACL = ReorderACL(objCopiedDACL)

' Write the DACL object back to the security descriptor
objSD.DiscretionaryAcl = objDACL

' Write the security descriptor back to the AD object
objAD.Put "ntSecurityDescriptor", Array(objSD)
objAD.SetInfo


And these are VbScript versions of the two functions called above (AddAce and ReorderACL):


Function AddAce(objDACL, strTrustee, intAccessMask, intAceType,_
            intAceFlags, intFlags, strObjectType, strInheritedObjectType)

      Dim objACE

      Set objACE = CreateObject("AccessControlEntry")
      objACE.AccessMask = intAccessMask
      objACE.AceType = intAccessType
      objACE.AceFlags = intAceFlags
      objACE.Flags = intFlags
      objACE.Trustee = strTrustee

      If CStr(strObjectType) <> "0" Then
           objACE.ObjectType = strObjectType
      End If

      If CStr(strInheritedObjectType) <> "0" Then
          objACE.InheritedObjectType = strInheritedObjectType
      End If

      objDACL.AddAce objACE
      Set objACE = Nothing
End Function

Function ReorderACL(objDacl)
      Dim objNewSD, objNewDACL, objImpDenyDACL, objImpDenyObjectDACL
      Dim objImpAllowDACL, objImpAllowObjectDACL, objACE

      Const ADS_ACETYPE_ACCESS_DENIED = &H1
      Const ADS_ACETYPE_ACCESS_DENIED_OBJECT = &H6
      Const ADS_ACETYPE_ACCESS_ALLOWED = &H0
      Const ADS_ACETYPE_ACCESS_ALLOWED_OBJECT = &H5
      Const ADS_ACEFLAG_INHERITED_ACE = &H10

      Set objNewSD = CreateObject("SecurityDescriptor")
      Set objNewDACL = CreateObject("AccessControlList")

      Set objImpDenyDACL = CreateObject("AccessControlList")
      Set objImpDenyObjectDACL = CreateObject("AccessControlList")
      Set objImpAllowDACL = CreateObject("AccessControlList")
      Set objImpAllowObjectDACL = CreateObject("AccessControlList")

      For Each objACE In objDACL
            Select Case objACE.AceType
                  Case ADS_ACETYPE_ACCESS_DENIED
                        objImpDenyDACL.AddAce objACE
                  Case ADS_ACETYPE_ACCESS_DENIED_OBJECT
                        objImpDenyObjectDACL.AddAce objACE
                  Case ADS_ACETYPE_ACCESS_ALLOWED
                        objImpAllowDACL.AddAce objACE
                  Case ADS_ACETYPE_ACCESS_ALLOWED_OBJECT
                        objImpAllowObjectDacl.AddAce objACE
                  Case Else
                        WScript.Echo "Bad ACE"
            End Select
      Next

      ' Combine the ACEs in the Proper Order
      ' Implicit Deny.
      For Each objACE In objImpDenyDACL
            objNewDACL.AddAce objACE
      Next

      ' Implicit Deny Object.
      For Each objACE In objImpDenyObjectDACL
            objNewDACL.AddAce objACE
      Next

      ' Implicit Allow.
      For Each objACEace In objImpAllowDACL
            objNewDACL.AddAce objACE
      Next

      ' Implicit Allow Object.
      For Each objACE In objImpAllowObjectDACL
            objNewDACL.AddAce objACE
      Next

      objNewDACL.AclRevision = objDACL.AclRevision

      Set ReorderACL = objNewDACL

      Set objNewDACL = Nothing
      Set objImpAllowObjectDACL = Nothing
      Set objImpAllowDACL = Nothing
      Set objImpDenyObjectDACL = Nothing
      Set objImpDenyDACL = Nothing
      Set objNewSD = Nothing
End Function
0
 
LVL 1

Author Comment

by:tim_storey
ID: 18849498
Whew Chris,
I am not worthy....
thanks for the effort, will give it all a whirl, been bashing my head on this for about 2 weeks now....

Tim
0
 
LVL 70

Expert Comment

by:Chris Dent
ID: 18849562

It's a pretty solid thing to bash your head against as well :)

Chris
0
 
LVL 1

Author Comment

by:tim_storey
ID: 18851346
It works,
the functions add and reorder perfectly, good stuff.

you get the points, deservedly, but I need to go a little further.....  ;)

I  need to try and figure out the intAccess mask's meaning, it would be good to know those values as I need to adapt this to use on other objects.  I am guessing this value is created form Or'ing the bitflags of the AccesMasks together?

So how did you get to intAccessMask = 131220 ? and as you say the mysterious 256

Would I be on the right track to Or together the AccessMasks and then see how it all comes out then?

Tim
0
 
LVL 70

Expert Comment

by:Chris Dent
ID: 18851912

You would, yes.

MS used to have a reference to all of them in MSDN but in a really helpful way it comes back with the "Content Not Found" mentioned above.

That leaves us with reverse engineering. Make the change and see what's changed.

I'll see if I can find another reference, and if I have time I'll install a virtual server and Exchange tonight so we can take it apart in a little more detail.

Chris
0

Featured Post

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

Follow this checklist to learn more about the 15 things you should never include in an email signature from personal quotes, animated gifs and out-of-date marketing content.
This article explains in simple steps how to renew expiring Exchange Server Internal Transport Certificate.
An introduction to basic programming syntax in Java by creating a simple program. Viewers can follow the tutorial as they create their first class in Java. Definitions and explanations about each element are given to help prepare viewers for future …
In this Micro Video tutorial you will learn the basics about Database Availability Groups and How to configure one using a live Exchange Server Environment. The video tutorial explains the basics of the Exchange server Database Availability grou…

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now