Modify the sidHistory attribute

Started by hienpham, December 01, 2015, 03:50:48 PM

Previous topic - Next topic

hienpham

Hello,
  I'm working on the sidHistory attributes in the Active Directory.
   I do not have any problem to read them using
         dsGetProperty(sUser, "sIDHistory")
    then extract them out using the WinBatch ItemCount and ItemExtract

  Now I need to remove some specific sidHistory attribute values (not all values) for several users accounts in the Active Directory.
  For that I read the sidHistory string, remove the unwanted item then write the remaining string back using
        dsSetProperty(suser,"sIDHistory", sid)
  I got the following error:
       " Wil Extender Error: 1027: The user has insufficient access right "
even though I use the Domain Admin context to run it.
   
To perform that action, VBScript successfully uses the following command:
     objectUser.PutEx ADS_PROPERTY_DELETE, "sIDHistory", array(sid)

with in Winbatch:
    objectUser = ObjectOpen(sUser)   
   ADS_PROPERTY_DELETE = 4

My question is how can I convert :
     objectUser.PutEx ADS_PROPERTY_DELETE, "sIDHistory", array(sid)
to WinBatch? 

Thanks.
 

hienpham

If I set in my Winbatch program:

          ADS_PROPERTY_DELETE = 4
          sid = "S-1-5-........" ; the correct sidHistory
          objectUser.PutEx(ADS_PROPERTY_DELETE, "sIDHistory",sid)

I get the following error:
      1261: COM/CLR: Exception
In the More Error Info, we have: 
          COM/CLR Exception:
          Unspecified error

To simplify the test the sid just has a single value.

Thanks

ChuckC

I don't know the specifics of the run-time error that you're getting, but I can provide some information about the sIDHistory attribute and the manipulation of it.

The sIDHistory attribute can only be written to for the purpose of setting a list of values or adding values by a very specific API function that gets called on a DC.  For some very obvious reasons, Microsoft has the write-access for this attribute severely limited, and you cannot modify it to add or set values thru any type of LDAP operation that affects "normal" attributes.

Individual SID values may be removed from the sIDHistory value list, and the entire attribute can also be removed.  You have to be a domain administrator in order to do this, though.

td

IIRC, ADSI COM Automation object method PutEx expects an variant array of byte arrays as the value to delete from the 'sIDHistory' property whether using WinBatch or VBS.  The byte arrays are arrays of VT_UI1 variants with each element containing one byte of the binary representation of a SID.   So if this is true, you can't just pass a string SID to PutEx and expect it to work.  The easiest way to get the byte arrays is to query the property for the full list then assign the SIDs you want to delete to a WILL array.  You may need to us ObjectType to cast the WIL array to a variant array before you perform the assignment to avoid potential method parameter type issues. 
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

hienpham

Thanks Tony and Chuck,
I got a request to remove not the whole SIDHistory string but only few components of it. And because I have to deal with thousands of users, it cannot be done manually.
  Your inputs are really very valuable to me, I will try to use them for my WinBatch program. Tony,specially the hint you gave me "assign the SIDs you want to delete to a WILL array" is what I did not think about.
I will let you guys know if I can get my WinBatch program work.
Thanks again.

hien

hienpham

Hi Tony and Chuck,
   My WinBatch script is:

        ADS_PROPERTY_DELETE = 4
   .....
   .....
             objectUser = ObjectOpen(sUser)
      vArray = objectUser.GetEx("sIDHistory")
        ForEach vSid in vArray
             objectUser.PutEx(ADS_PROPERTY_DELETE, "sIDHistory", vSid)
             objectUser.SetInfo
        Next

   At the line:              objectUser.PutEx(ADS_PROPERTY_DELETE, "sIDHistory", vSid)
    I got the following error:
            1261:  COM/CLR: Exception
in the More Error Info:   COM/CLR Exception: 
                                    Active Directory
                                    Unspecified Error

What did I do wrong?
  Thanks for your help




td

If your purpose is to delete all SIDs then try passing the vArray variable instead of vSid.  As previously mentioned, the PutEx may be expecting an array of byte arrays instead of a byte array.  If you don't want to delete all SIDs, try removing the SIDs you don't want to delete from the array using ArrayRemove before passing vArray to PutEx.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

hienpham

Thanks Tony for your Great help. With your advice I made some progress but my problem was not completly solved.

I'm able now to remove all the SIDs of SidHistory attribute by passing the vArray variable as below:
        ADS_PROPERTY_DELETE = 4
        ....
        vArray = objectUser.GetEx("sIDHistory") 
        objectUser.PutEx(ADS_PROPERTY_DELETE, "sIDHistory", vArray)
        objectUser.SetInfo

   this part runs without any single problem and the all the SIDs get delete (I did verify it by looking at the Active Directory)

but when I try just to delete only 1 SID with the following codes:
        ADS_PROPERTY_UPDATE  = 2
         .....
        vArray = objectUser.GetEx("sIDHistory")
        ArrayRemove(vArray,ss_rem)   ;  ss_rem is the element number of the array that I want to remove
        objectUser.PutEx(ADS_PROPERTY_UPDATE, "sIDHistory", vArray)
        objectUser.SetInfo

There is no Error with the PutEx but at the SetInfo I got "Active Directory Access is Denied" (Error 1261: COM/CLR: Exception) even though I ran this script witht the same context with the one I used to run the "deletion" part.
I also test by commenting out the ArrayRemove command to keep the vArray unchanged, but I still got the same Access Denied error at the SetInfo command.
         ADS_PROPERTY_UPDATE  = 2
         .....
        vArray = objectUser.GetEx("sIDHistory")
        ;         ArrayRemove(vArray,ss_rem)   ;  ss_rem is the element number of the array that I want to remove
        objectUser.PutEx(ADS_PROPERTY_UPDATE, "sIDHistory", vArray)
        objectUser.SetInfo

Why SetInfo command did not have problem with ADS_PROPERTY_DELETE but only with ADS_PROPERTY_UPDATE, while both ADS_ modify the sisHistory attribute?

td

ChuckC already explained this.  Please read or reread his post above.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

hienpham

Thanks Tony,
   Chuck said " Individual SID values may be removed from the sIDHistory value list " and "You have to be a domain administrator in order to do this, though"
   I'm the domain admin (and ran the script under this context) and tried to remove the Individual SID. I did not have any problem removing ALL the SIDs at the same time but failed to remove one of them.
   
Thanks.

td

You asked about being able to update the property, i.e., ADS_PROPERTY_UPDATE and to quote Chuck, 'For some very obvious reasons, Microsoft has the write-access for this attribute severely limited, and you cannot modify it to add or set values thru any type of LDAP operation that affects "normal" attributes.'

In other words, you can only use ADS_PROPERTY_DELETE with an array of byte arrays of the SIDs you wish to delete.
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

ChuckC

ADS_PROPERTY_UPDATE is simply not allowed to be used with the sIDHistory attribute.

ADS_PROPERTY_DELETE will allow one or more specific SID values to be removed from the attribute's value list, and ADS_PROPERTY_CLEAR will remove the entire attribute from the object.

That's *all* that you can do with the sIDHistory attribute w/respect to modifying it via LDAP.  The update/append operations are blocked by domain controllers, and aren't permitted to be performed regardless of what group memberships you have or permissions you have applied to the object and attribute.  This is known as an "operational limit", in that it's enforced by program code rather than the normal access-check mechanism for discretionary access control.


hienpham

Thanks again both of you for your very valuable help.
I got my script working!!

I was able to use the ADS_PROPERTY_DELETE and the ArrayRemove command to delete the SID that I need to remove.
For example there is an account that has 4 SIDs in the SIDHistory and I need to remove the 3rd SID of the list, what I did was to apply the ArrayRemove on the 1st, 2nd, and 4th array elements.
The remaining array just has the 3rd item of the SISHistory that I want to remove. JUst apply ADS_PROPERTY_DELETE to the to the SIDHistory using that array.
Everything works perfectly.

Thanks so much for your time Tony and Chuck.

Hien