@@ -120,10 +120,22 @@ private static Dictionary<string, object> GetCommonProperties(IDirectoryObject e
120120 return props ;
121121 }
122122
123+ // Helper method to handle AdminSDHolder processing
124+ private string GetAdminSdHolderHash ( string domain )
125+ {
126+ if ( _context . AdminSDHolderHash != null &&
127+ _context . AdminSDHolderHash . TryGetValue ( domain , out var hash ) )
128+ {
129+ return hash ;
130+ }
131+ return null ;
132+ }
123133
124134 private async Task < User > ProcessUserObject ( IDirectoryObject entry ,
125- ResolvedSearchResult resolvedSearchResult ) {
126- var ret = new User {
135+ ResolvedSearchResult resolvedSearchResult )
136+ {
137+ var ret = new User
138+ {
127139 ObjectIdentifier = resolvedSearchResult . ObjectId
128140 } ;
129141
@@ -134,7 +146,11 @@ private async Task<User> ProcessUserObject(IDirectoryObject entry,
134146 if ( entry . IsGMSA ( ) ) ret . Properties . Add ( "gmsa" , true ) ;
135147 ret . DomainSID = resolvedSearchResult . DomainSid ;
136148
137- if ( _methods . HasFlag ( CollectionMethod . ACL ) ) {
149+ if ( _methods . HasFlag ( CollectionMethod . ACL ) )
150+ {
151+ // AdminSDHolderProtected only on security principal nodes: User, Computer, Group
152+ var adminSdHolderHash = GetAdminSdHolderHash ( resolvedSearchResult . Domain ) ;
153+
138154 var aces = await _aclProcessor . ProcessACL ( resolvedSearchResult , entry , true )
139155 . ToArrayAsync ( cancellationToken : _cancellationToken ) ;
140156 ret . Properties . Add ( "doesanyacegrantownerrights" , aces . Any ( ace => ace . IsPermissionForOwnerRightsSid ) ) ;
@@ -144,17 +160,25 @@ private async Task<User> ProcessUserObject(IDirectoryObject entry,
144160 . ToArrayAsync ( cancellationToken : _cancellationToken ) ) . ToArray ( ) ;
145161 ret . IsACLProtected = _aclProcessor . IsACLProtected ( entry ) ;
146162 ret . Properties . Add ( "isaclprotected" , ret . IsACLProtected ) ;
163+ var isAdminSdHolderProtected = _aclProcessor . IsAdminSDHolderProtected ( entry , adminSdHolderHash ) ;
164+ if ( isAdminSdHolderProtected != null )
165+ {
166+ ret . Properties . Add ( "adminsdholderprotected" , isAdminSdHolderProtected ) ;
167+ }
147168 }
148169
149- if ( _methods . HasFlag ( CollectionMethod . Group ) ) {
170+ if ( _methods . HasFlag ( CollectionMethod . Group ) )
171+ {
150172 var pg = entry . GetProperty ( LDAPProperties . PrimaryGroupID ) ;
151173 ret . PrimaryGroupSID = GroupProcessor . GetPrimaryGroupInfo ( pg , resolvedSearchResult . ObjectId ) ;
152174 }
153175
154- if ( _methods . HasFlag ( CollectionMethod . ObjectProps ) ) {
176+ if ( _methods . HasFlag ( CollectionMethod . ObjectProps ) )
177+ {
155178 var userProps = await _ldapPropertyProcessor . ReadUserProperties ( entry , resolvedSearchResult ) ;
156179 ret . Properties = ContextUtils . Merge ( ret . Properties , userProps . Props ) ;
157- if ( _context . Flags . CollectAllProperties ) {
180+ if ( _context . Flags . CollectAllProperties )
181+ {
158182 ret . Properties = ContextUtils . Merge ( _ldapPropertyProcessor . ParseAllProperties ( entry ) ,
159183 ret . Properties ) ;
160184 }
@@ -164,14 +188,17 @@ private async Task<User> ProcessUserObject(IDirectoryObject entry,
164188 ret . UnconstrainedDelegation = userProps . UnconstrainedDelegation ;
165189 }
166190
167- if ( _methods . HasFlag ( CollectionMethod . SPNTargets ) ) {
191+ if ( _methods . HasFlag ( CollectionMethod . SPNTargets ) )
192+ {
168193 ret . SPNTargets = await _spnProcessor . ReadSPNTargets ( resolvedSearchResult , entry )
169194 . ToArrayAsync ( cancellationToken : _cancellationToken ) ;
170195 }
171196
172- if ( _methods . HasFlag ( CollectionMethod . Container ) ) {
197+ if ( _methods . HasFlag ( CollectionMethod . Container ) )
198+ {
173199 if ( entry . TryGetDistinguishedName ( out var dn ) &&
174- await _containerProcessor . GetContainingObject ( dn ) is ( true , var container ) ) {
200+ await _containerProcessor . GetContainingObject ( dn ) is ( true , var container ) )
201+ {
175202 ret . ContainedBy = container ;
176203 }
177204 }
@@ -197,14 +224,23 @@ Channel<CSVComputerStatus> compStatusChannel
197224 ret . IsDC = resolvedSearchResult . IsDomainController ;
198225 ret . DomainSID = resolvedSearchResult . DomainSid ;
199226
200- if ( _methods . HasFlag ( CollectionMethod . ACL ) ) {
227+ if ( _methods . HasFlag ( CollectionMethod . ACL ) )
228+ {
229+ // AdminSDHolderProtected only on security principal nodes: User, Computer, Group
230+ var adminSdHolderHash = GetAdminSdHolderHash ( resolvedSearchResult . Domain ) ;
231+
201232 var aces = await _aclProcessor . ProcessACL ( resolvedSearchResult , entry , true )
202233 . ToArrayAsync ( cancellationToken : _cancellationToken ) ;
203234 ret . Properties . Add ( "doesanyacegrantownerrights" , aces . Any ( ace => ace . IsPermissionForOwnerRightsSid ) ) ;
204235 ret . Properties . Add ( "doesanyinheritedacegrantownerrights" , aces . Any ( ace => ace . IsInheritedPermissionForOwnerRightsSid ) ) ;
205236 ret . Aces = aces ;
206237 ret . IsACLProtected = _aclProcessor . IsACLProtected ( entry ) ;
207238 ret . Properties . Add ( "isaclprotected" , ret . IsACLProtected ) ;
239+ var isAdminSdHolderProtected = _aclProcessor . IsAdminSDHolderProtected ( entry , adminSdHolderHash ) ;
240+ if ( isAdminSdHolderProtected != null )
241+ {
242+ ret . Properties . Add ( "adminsdholderprotected" , isAdminSdHolderProtected ) ;
243+ }
208244 }
209245
210246 if ( _methods . HasFlag ( CollectionMethod . Group ) ) {
@@ -329,7 +365,7 @@ await compStatusChannel.Writer.WriteAsync(new CSVComputerStatus {
329365 // var cred = _context.Flags.DoLocalAdminSessionEnum
330366 // ? new NetworkCredential(_context.LocalAdminUsername, _context.LocalAdminPassword, ".")
331367 // : null;
332- //
368+ //
333369 // var evntProcessor = new EventLogProcessor(
334370 // _context.LDAPUtils,
335371 // _log,
@@ -378,11 +414,11 @@ private async void ProcessDomainController(ResolvedSearchResult resolvedSearchRe
378414 ret . Properties . Add ( "ldapavailable" , ldapServices . HasLdap ) ;
379415 ret . Properties . Add ( "ldapsavailable" , ldapServices . HasLdaps ) ;
380416 if ( ldapServices . IsChannelBindingDisabled . Collected ) {
381- ret . Properties . Add ( "ldapsepa" , ! ldapServices . IsChannelBindingDisabled . Result ) ;
417+ ret . Properties . Add ( "ldapsepa" , ! ldapServices . IsChannelBindingDisabled . Result ) ;
382418 }
383419
384420 if ( ldapServices . IsSigningRequired . Collected ) {
385- ret . Properties . Add ( "ldapsigning" , ldapServices . IsSigningRequired . Result ) ;
421+ ret . Properties . Add ( "ldapsigning" , ldapServices . IsSigningRequired . Result ) ;
386422 }
387423 }
388424 }
@@ -396,14 +432,23 @@ private async Task<Group> ProcessGroupObject(IDirectoryObject entry,
396432 ret . Properties = new Dictionary < string , object > ( GetCommonProperties ( entry , resolvedSearchResult ) ) ;
397433 ret . Properties . Add ( "samaccountname" , entry . GetProperty ( LDAPProperties . SAMAccountName ) ) ;
398434
399- if ( _methods . HasFlag ( CollectionMethod . ACL ) ) {
435+ if ( _methods . HasFlag ( CollectionMethod . ACL ) )
436+ {
437+ // AdminSDHolderProtected only on security principal nodes: User, Computer, Group
438+ var adminSdHolderHash = GetAdminSdHolderHash ( resolvedSearchResult . Domain ) ;
439+
400440 var aces = await _aclProcessor . ProcessACL ( resolvedSearchResult , entry , true )
401441 . ToArrayAsync ( cancellationToken : _cancellationToken ) ;
402442 ret . Properties . Add ( "doesanyacegrantownerrights" , aces . Any ( ace => ace . IsPermissionForOwnerRightsSid ) ) ;
403443 ret . Properties . Add ( "doesanyinheritedacegrantownerrights" , aces . Any ( ace => ace . IsInheritedPermissionForOwnerRightsSid ) ) ;
404444 ret . Aces = aces ;
405445 ret . IsACLProtected = _aclProcessor . IsACLProtected ( entry ) ;
406446 ret . Properties . Add ( "isaclprotected" , ret . IsACLProtected ) ;
447+ var isAdminSdHolderProtected = _aclProcessor . IsAdminSDHolderProtected ( entry , adminSdHolderHash ) ;
448+ if ( isAdminSdHolderProtected != null )
449+ {
450+ ret . Properties . Add ( "adminsdholderprotected" , isAdminSdHolderProtected ) ;
451+ }
407452 }
408453
409454 if ( _methods . HasFlag ( CollectionMethod . Group ) )
0 commit comments