Solved

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

Posted on 2007-04-02
11
1,775 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 4
11 Comments
 
LVL 71

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 71

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
Get 15 Days FREE Full-Featured Trial

Benefit from a mission critical IT monitoring with Monitis Premium or get it FREE for your entry level monitoring needs.
-Over 200,000 users
-More than 300,000 websites monitored
-Used in 197 countries
-Recommended by 98% of users

 
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 71

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
 
LVL 71

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 71

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 71

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 71

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

On Demand Webinar: Networking for the Cloud Era

Ready to improve network connectivity? Watch this webinar to learn how SD-WANs and a one-click instant connect tool can boost provisions, deployment, and management of your cloud connection.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

After hours on line I found a solution which pointed to the inherited Active Directory permissions . You have to give/allow permissions to the "Exchange trusted subsystem" for the user in the Active Directory...
Q&A with Course Creator, Mark Lassoff, on the importance of HTML5 in the career of a modern-day developer.
The basic steps you have just learned will be implemented in this video. The basic steps are shown to configure an Exchange DAG in a live working Exchange Server Environment and manage the same (Exchange Server 2010 Software is used in a Windows Ser…
In this fifth video of the Xpdf series, we discuss and demonstrate the PDFdetach utility, which is able to list and, more importantly, extract attachments that are embedded in PDF files. It does this via a command line interface, making it suitable …
Suggested Courses

630 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