0

I am aware of CheckMaxTokenSize.ps1 (and unfortunately TokenSZ.exe is no longer available, and only works in 32 bit OS), how would I calculate max token size for a specific computer object? I was able to modify a script to find the total number of recursive membership objects (there is a hard MS max of 1015 per computer), but need to take it further.

here is that simple powershell script

Import-Module ActiveDirectory
$forestName = ([System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()).Name
$ADsPath = [ADSI]"GC://$forestName"
$Search = New-Object System.DirectoryServices.DirectorySearcher($ADsPath)
$computer = Read-Host "Computer Name"
Write-Host ""; Write-Host "Processing....." -nonewline
if ($computer -eq "") {$computer = "<BLANK>"}
$Search.Filter = "(&(objectCategory=Computer)(name=$computer))"
$computercn = $Search.FindAll().Properties.distinguishedname
$csv = dsget computer $computercn -memberof -expand
Write-Host ($csv.Length -1) "items in List" -ForegroundColor Green
Write-Host "-----------------------------------"

How would I return Token Size of the AD computer object without being on the device?

  • The `ActiveDirectory` module, a `DirectorySearcher` instance *and* `dsget` - you really can't decide which toolset to use, can you? In any case, what is the actual question here? Are you unsure of the formula for calculating the maximum token size? – Mathias R. Jessen Mar 30 '17 at 16:28
  • I know the formula, but don't have the knowledge to implement it. I'm not a scripter, just trying to fudge a solution. I apologize for the sloppiness. The actual question is "how do I get this messy script to calculate max token size so I can make sure it's under 65535" – Brent Surphlis Mar 30 '17 at 16:36

1 Answers1

0

I would suggest you start over and really review what information you need in order to break down this task into simple steps.

Before we begin, let's review the token size formula:

TokenSize = 1200 + 40d + 8s

This formula uses the following values:
d: The number of domain local groups a user is a member of plus the number of universal groups outside the user's account domain that the user is a member of plus the number of groups represented in security ID (SID) history.
s: The number of security global groups that a user is a member of plus the number of universal groups in a user's account domain that the user is a member of.
1200: The estimated value for ticket overhead. This value can vary, depending on factors such as DNS domain name length, client name, and other factors.

Assuming that you have the computer name already (potentially from user input), what we need is:

  1. Retrieve the computer account object, with its sid history
  2. Find all its group memberships (recursively)
  3. Split the groups into two buckets based on domain and scope

So, let's get to work. Since you have the ActiveDirectory module handy, finding the computer is easy:

# Define computer name
$ComputerName = "computer01"

# Find the computer in the directory
$Computer = Get-ADComputer -LDAPFilter "(&(name=$ComputerName))" -Properties PrimaryGroup,SidHistory

Now, we could use the Get-ADPrincipalGroupMembership cmdlet to retrieve all the group memberships, but it doesn't support recursive searches, so I would use the IN_CHAIN query rule control in an LDAP filter with Get-ADGroup:

# Locate a Global Catalog server
$GC = Get-ADDomainController -Discover -Service GlobalCatalog

# Search the global catalog using our recursive ldap filter
$Groups = Get-ADGroup -LDAPFilter "(&(member:1.2.840.113556.1.4.1941:=$($Computer.DistinguishedName)))" -Server "$($GC.HostName):3268"

# Don't forget the primary group
$Groups = @($Groups; Get-ADGroup -Identity $Computer.PrimaryGroup)

Now we just need to split the groups into two sets, one containing Domain Local groups and foreign Universal Groups, and one containing Global groups and local Universal groups:

# These are the "d" groups from the original formula
$LargeGroups = @($Groups |Where-Object {$_.GroupScope -eq 'DomainLocal' -or ($_.GroupScope -eq 'Universal' -and $_.DistinguishedName -notlike "*,DC=$($GC.Domain -split '\.' -join ',DC=')")})

# These are the "s" groups from the original formula
$SmallGroups = @($Groups |Where-Object {$_.GroupScope -eq 'Global' -or ($_.GroupScope -eq 'Universal' -and $_.DistinguishedName -like "*,DC=$($GC.Domain -split '\.' -join ',DC=')")})

Now just calculate according to the formula:

# Calculate TokenSize based on groups
$TokenSize = 1200 + (40 * $LargeGroups.Count) + (8 * $SmallGroups.Count)

# Factory in SIDHistory principals
if($Computer.SIDHistory){
    $TokenSize += 40 * $Computer.SIDHistory.Count 
}

And we're done :-)

Community
  • 1
  • 1
Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206
  • $largegroups and $smallgroups are empty :( the script is complaining that get-adgroup search filter cannot be recognized, and that Identity has a null argument – Brent Surphlis Mar 30 '17 at 18:29
  • Does $Computer contain anything? – Mathias R. Jessen Mar 30 '17 at 19:17
  • no. groups, gc do however (thanks for all this by the way) – Brent Surphlis Mar 30 '17 at 19:24
  • Well then you know what the issue is ☺ make sure $ComputerName contains a correct/existing computer name – Mathias R. Jessen Mar 30 '17 at 19:29
  • it does though :) I can't get $Computer = Get-ADComputer -LDAPFilter "(&(name=$ComputerName))" -Properties PrimaryGroup,SidHistory to work, even if ComputerName has a valid computer – Brent Surphlis Mar 30 '17 at 19:37
  • I know why this wasn't working... two reasons, 1) I was logged into a different domain, that's on me whoops, 2) my Domain is too large, so I doubt get-ADGroup is going to work :( Get-ADGroup : This operation returned because the timeout period expired – Brent Surphlis Mar 31 '17 at 14:00