Skip to content

Instantly share code, notes, and snippets.

@ktwombley
Created June 28, 2019 14:52
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ktwombley/005b7feaa7bb5ec9dd651784c4759ec4 to your computer and use it in GitHub Desktop.
Save ktwombley/005b7feaa7bb5ec9dd651784c4759ec4 to your computer and use it in GitHub Desktop.
# Convert-ADName.ps1
# Written by Bill Stewart (bstewart@iname.com)
# PowerShell wrapper script for the NameTranslate COM object.
#requires -version 2
<#
.SYNOPSIS
Translates Active Directory names between various formats.
.DESCRIPTION
Translates Active Directory names between various formats using the NameTranslate COM object. Before names can be translated, the NameTranslate object must first be initialized. The default initialization type is 'GC' (see the -InitType parameter). You can use the -Credential parameter to initialize the NameTranslate object using specific credentials.
.PARAMETER Name
The name to translate.
.PARAMETER InputType
The input name type. Possible values are the same as -OutputType, with the following additions:
unknown I'm gonna just guess.
SIDorSIDhistory SDDL string for the SID or one from the object's SID history
The default value for this parameter is 'unknown'.
.PARAMETER OutputType
The output name type, which must be one of the following:
1779 : CN=Smith\, John,OU=Staff,OU=Users,DC=contoso,DC=com
DN : CN=Smith\, John,OU=Staff,OU=Users,DC=contoso,DC=com
canonical : contoso.com/Users/Staff/Smith, John
NT4 : CONTOSO\JSMITH
display : Smith, John
domainSimple : JSMITH@CONTOSO.COM
enterpriseSimple : JSMITH@CONTOSO.COM
GUID : {4fdc0ae3-8aa4-4ba9-9c75-a4b33f26fabc}
UPN : JSMITH@CONTOSO.COM
canonicalEx : contoso.com/Users/Staff
Smith, John
SPN : www/www.contoso.com:80/cn=spiderman,ou=webmaster,dc=contoso,dc=com
SID : S-1-5-21-1234567890-432198765-987654321-12345
.PARAMETER SearchType
The type of initialization to be performed, which must be one of the following:
domain Bind to the domain specified by the -InitName parameter
server Bind to the server specified by the -InitName parameter
GC Locate and bind to a global catalog
The default value for this parameter is 'GC'. When -InitType is not 'GC', you must also specify the -SearchWhere parameter.
.PARAMETER SearchWhere
When -SearchType is 'domain' or 'server', this parameter specifies which domain or server to bind to. This parameter is ignored if -SearchType is 'GC'.
.PARAMETER ChaseReferrals
This parameter specifies whether to chase referrals. (When a server determines that other servers hold relevant data, in part or as a whole, it may refer the client to another server to obtain the result. Referral chasing is the action taken by a client to contact the referred-to server to continue the directory search.)
.PARAMETER Credential
Use the specified credentials.
.EXAMPLE
PS C:\> Convert-ADName -OutputType dn -Name fabrikam\pflynn
This command outputs the specified domain\username as a distinguished name.
PS C:\> Convert-ADName canonical 'CN=Phineas Flynn,OU=Engineers,DC=fabrikam,DC=com'
This command outputs the specified DN as a canonical name.
PS C:\> Convert-ADName dn fabrikam\pflynn -InitType server -InitName dc1
This command uses the server dc1 to translate the specified name.
PS C:\> Convert-ADName display fabrikam\pflynn -InitType domain -InitName fabrikam
This command uses the fabrikam domain to translate the specified name.
PS C:\> Convert-ADName dn 'fabrikam.com/Engineers/Phineas Flynn' -Credential (Get-Credential)
Prompts for credentials, then uses those credentials to translate the specified name.
PS C:\> Get-Content DNs.txt | Convert-ADName -OutputType display -InputType dn
Outputs the display names for each of the distinguished names in the file DNs.txt.
#>
function Convert-ADName {
[CmdletBinding()]
param(
#Name to translate
[parameter(Mandatory=$true,ValueFromPipeline=$true)]
[String[]] $Name,
[ValidateSet("1779","DN","canonical","NT4","display","domainSimple","enterpriseSimple","GUID","UPN","canonicalEx","SPN","unknown","SIDorSidHistory")]
[String] $InputType="unknown",
[parameter(Mandatory=$true)]
[ValidateSet("1779","DN","canonical","NT4","display","domainSimple","enterpriseSimple","GUID","UPN","canonicalEx","SPN","SID","dnsdomainname")]
[String] $OutputType,
[ValidateSet("domain","server","GC")]
[String] $SearchType="GC",
[String] $SearchWhere=$null,
[Switch] $ChaseReferrals,
[System.Management.Automation.PSCredential] $Credential = $null
)
begin {
# Hash table to simplify output type names and values
$OutputNameTypes = @{
"1779" = 1;
"DN" = 1;
"canonical" = 2;
"NT4" = 3;
"display" = 4;
"domainSimple" = 5;
"enterpriseSimple" = 6;
"GUID" = 7;
"UPN" = 9;
"canonicalEx" = 10;
"SPN" = 11;
"SID" = 12;
}
# Copy output type hash table and add two additional types
$InputNameTypes = $OutputNameTypes.Clone()
$InputNameTypes.Add("unknown", 8)
$InputNameTypes.Add("SIDorSidHistory", 12)
# Same as with previous hash tables...
$InitNameTypes = @{
"domain" = 1;
"server" = 2;
"GC" = 3;
}
if ( ($SearchType -ne "GC") -and ($SearchWhere -eq "") ) {
write-error "The -SearchWhere parameter cannot be empty when searching a domain or server." -category InvalidArgument
exit
}
# Accessor functions to simplify calls to NameTranslate
function invoke-method([__ComObject] $object, [String] $method, $parameters) {
$output = $object.GetType().InvokeMember($method, "InvokeMethod", $NULL, $object, $parameters)
if ( $output ) { $output }
}
function get-property([__ComObject] $object, [String] $property) {
$object.GetType().InvokeMember($property, "GetProperty", $NULL, $object, $NULL)
}
function set-property([__ComObject] $object, [String] $property, $parameters) {
[Void] $object.GetType().InvokeMember($property, "SetProperty", $NULL, $object, $parameters)
}
# Create the NameTranslate COM object
$NameTranslate = new-object -comobject NameTranslate
# If -Credential, use InitEx to initialize it; otherwise, use Init
if ( $Credential ) {
$networkCredential = $Credential.GetNetworkCredential()
try {
invoke-method $NameTranslate "InitEx" (
$InitNameTypes[$SearchType],
$SearchWhere,
$networkCredential.UserName,
$networkCredential.Domain,
$networkCredential.Password
)
}
catch [System.Management.Automation.MethodInvocationException] {
write-error $_
exit
}
finally {
remove-variable networkCredential
}
}
else {
try {
invoke-method $NameTranslate "Init" (
$InitNameTypes[$SearchType],
$SearchWhere
)
}
catch [System.Management.Automation.MethodInvocationException] {
write-error $_
exit
}
}
# If -ChaseReferrals, set the object's ChaseReferral property to 0x60
if ( $ChaseReferrals ) {
set-property $NameTranslate "ChaseReferral" (0x60)
}
# The NameTranslate object's Set method specifies the name to translate and
# its input format, and the Get method returns the name in the output format
function Convert-ADName2([String] $in, [Int] $inputType, [Int] $outputType) {
try {
invoke-method $NameTranslate "Set" ($inputType, $in)
invoke-method $NameTranslate "Get" ($outputType)
}
catch [System.Management.Automation.MethodInvocationException] {
write-error "'$Name' - $($_.Exception.InnerException.Message)"
}
}
#Set up for dealing with 'dnsdomainname' output format.
$dns_translate = $false
[hashtable]$domcache = @{}
if ($OutputType -eq 'dnsdomainname') {
$dns_translate = $true
$OutputType = 'NT4'
}
}
process {
foreach($aninp in $Name) {
$x = Convert-ADName2 $aninp $InputNameTypes[$InputType] $OutputNameTypes[$OutputType]
if ($dns_translate) {
$legacy,$uname = $x -split '\\'
if ($legacy -and $uname) {
try {
if ($domcache.ContainsKey($legacy)) {
$dom = $domcache[$legacy]
} else {
$dom = Get-ADDomain -Identity $legacy
$domcache.Add($legacy,$dom)
}
$x = "$($dom.DNSRoot)\$uname"
} catch {
#leave X alone
}
}
}
$x
}
}
end {
$domcache.Clear()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment