-
-
Save AnwarYagoub/2700c23b278cab10fadf72e05d38ae9d to your computer and use it in GitHub Desktop.
Functions for converting a SID to a UID for use with RFC2307 attributes in Active Directory
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Get-UidFromSid | |
{ | |
[CmdletBinding()] | |
param( | |
[Parameter(Mandatory=$true,Position=0,ValueFromPipeline,ValueFromPipelineByPropertyName)] | |
[System.Security.Principal.SecurityIdentifier]$sid | |
) | |
Process { | |
# convert sid to byte array | |
$sidBytes = New-Object byte[] $sid.BinaryLength | |
$sid.GetBinaryForm($sidBytes, 0) | |
Write-Verbose ("SID bytes: $([System.BitConverter]::ToString($sidBytes))") | |
# copy the sections we need | |
$ridDomainBytes = New-Object byte[] 8 | |
[System.Array]::Copy($sidBytes, 16, $ridDomainBytes, 0, 4) | |
$ridUserBytes = New-Object byte[] 8 | |
[System.Array]::Copy($sidBytes, 24, $ridUserBytes, 0, 4) | |
Write-Verbose ("Domain portion: $([System.BitConverter]::ToString($ridDomainBytes))") | |
Write-Verbose ("User portion: $([System.BitConverter]::ToString($ridUserBytes))") | |
# fix endian'ness if necessary | |
if (![System.BitConverter]::IsLittleEndian) | |
{ | |
[System.Array]::Reverse($ridDomainBytes) | |
[System.Array]::Reverse($ridUserBytes) | |
} | |
# convert the byte arrays to longs | |
$ridDomain = [System.BitConverter]::ToInt64($ridDomainBytes, 0); | |
$ridUser = [System.BitConverter]::ToInt64($ridUserBytes, 0); | |
Write-Verbose "Domain(Int64) = $ridDomain, User(Int64) = $ridUser" | |
# Now we're going to use the first 9 bits of the domain rid followed by the | |
# first 22 bits of the user rid to make a single 31 bit integer (32-bit signed) | |
# that will be the new unique UID value for this SID | |
$ridDomain = ($ridDomain -band 0x1ff) -shl 22 | |
$ridUser = $ridUser -band 0x3fffff | |
Write-Verbose "Domain(Int64) = $ridDomain, User(Int64) = $ridUser" | |
return ($ridDomain + $ridUser) | |
} | |
<# | |
.SYNOPSIS | |
Calculate the UID value for a Windows SID. | |
.DESCRIPTION | |
This function duplicates Centrify's algorithm for generating unique UID | |
values for Active Directory users and groups. The original algorithm was | |
provided by Centrify and ported to PowerShell by Ryan Bolger. | |
.PARAMETER sid | |
The SecurityIdentifier (SID) object to calculate against. | |
.OUTPUTS | |
System.Int32 value of the resulting UID. | |
.EXAMPLE | |
Get-UidFromSid ([System.Security.Principal.SecurityIdentifier]'S-1-5-21-3040497277-3966670145-4188292625-1137') | |
Calculate a UID from a fictional SID. | |
.EXAMPLE | |
Get-ADUser myuser | Get-UidFromSid | |
Calculate a UID from an existing Active Directory user via pipeline input. | |
#> | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// using System; | |
// using System.Security.Principal; | |
public static long GetUidFromSid(SecurityIdentifier sid) | |
{ | |
//convert to byte array | |
byte[] sidBytes = new byte[sid.BinaryLength]; | |
sid.GetBinaryForm(sidBytes, 0); | |
// copy the sections we need | |
byte[] ridDomainBytes = new byte[8]; | |
Array.Copy(sidBytes, 16, ridDomainBytes, 0, 4); | |
byte[] ridUserBytes = new byte[8]; | |
Array.Copy(sidBytes, 24, ridUserBytes, 0, 4); | |
// fix endian'ness if necessary | |
if (!BitConverter.IsLittleEndian) | |
{ | |
Array.Reverse(ridDomainBytes); | |
Array.Reverse(ridUserBytes); | |
} | |
// convert the byte arrays to longs | |
long ridDomain = BitConverter.ToInt64(ridDomainBytes, 0); | |
long ridUser = BitConverter.ToInt64(ridUserBytes, 0); | |
// Now we're going to use the first 9 bits of the domain rid followed by the | |
// first 22 bits of the user rid to make a single 31 bit integer (32-bit signed) | |
// that will be the new unique UID value for this SID | |
ridDomain = (ridDomain & 0x1ff) << 22; | |
ridUser = ridUser & 0x3fffff; | |
return (ridDomain + ridUser); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import print_function | |
import sys | |
# This script is designed to accept a SID in SDDL format from stdin and output | |
# a UID value that can be used in the uidNumber or gidNumber attribute on an | |
# Active Directory domain object. The algorithm was originally provided by | |
# Centrify and has been ported to Python by Ryan Bolger. | |
# The code was originally written for Python 2.6.6 on RHEL 6 and has also been | |
# tested with Python 2.7.6 on Windows. | |
# All verbose output should be written to stderr and the only output in stdout | |
# should be the UID/GID value. | |
# Usage examples: | |
# | |
# echo S-1-5-21-3040497277-3966670145-4188292625-1137 | python SIDtoUID.py | |
# adquery user da06076 --sid | python SIDtoUID.py | |
# | |
# The SID in the example above should convert to UID 1346372721 | |
def SIDtoUID(strSid): | |
# An Active Directory SID in SDDL form for non-built-in users/groups should | |
# always be in the following format: | |
# S-1-5-21-XXXXXXXXXX-XXXXXXXXXXX-XXXXXXXXXX-YYYY | |
# The X's are three 32-bit integers that comprise the 96-bit randomly | |
# generated domain identifier | |
# The Y's are a single 32-bit integer that is the object's relative ID in | |
# the domain (RID) | |
# For the purpose of this algorithm, we only care about the second section of | |
# the domain identifier and the user/group RID. So instead of fully parsing | |
# the complete SDDL into its binary form, we're going to take a short cut and | |
# just grab those chunks with only some basic sanity checking. | |
# make sure the beginning looks right | |
if not strSid.startswith('S-1-5-21-'): | |
print("ERROR: SID string was invalid.", file=sys.stderr) | |
exit(1) | |
# make sure we have the right number of elements | |
elements = strSid.upper().split("-") | |
if len(elements) != 8: | |
print("ERROR: Not enough sub-authority elements found.", file=sys.stderr) | |
exit(1) | |
# grab the elements we care about | |
ridDomain = int(elements[5]) | |
ridUser = int(elements[7]) | |
# Now we're going to use the first 9 bits of the domain rid followed by the | |
# first 22 bits of the user rid to make a single 31 bit integer (32-bit signed) | |
# that will be the new unique UID value for this SID | |
ridDomain = (ridDomain & 0x1ff) << 22 | |
ridUser = ridUser & 0x3fffff | |
uid = ridDomain + ridUser | |
return uid | |
for line in sys.stdin: | |
print(SIDtoUID(line)) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# This script is designed to accept a SID in SDDL format from stdin and output | |
# a UID value that can be used in the uidNumber or gidNumber attribute on an | |
# Active Directory domain object. The algorithm was originally provided by | |
# Centrify and has been ported to Bash by Ryan Bolger. | |
# All verbose output should be written to stderr and the only output in stdout | |
# should be the UID/GID value. | |
# Usage examples: | |
# | |
# echo S-1-5-21-3040497277-3966670145-4188292625-1137 | ./SIDtoUID.sh | |
# adquery user da06076 --sid | ./SIDtoUID.sh | |
# | |
# The SID in the example above should convert to UID 1346372721 | |
set -o nounset -o pipefail | |
#set -x | |
SIDtoUID() | |
{ | |
# make sure the beginning looks right | |
if [[ $1 != S-1-5-21-* ]]; then | |
>&2 echo "ERROR: SID string was invalid." | |
exit 1 | |
fi | |
# make sure we have the right number of elements | |
IFS='-' read -ra elements <<< "$1" | |
if [[ ${#elements[@]} != 8 ]]; then | |
>&2 echo "ERROR: Not enough sub-authority elements found." | |
exit 1 | |
fi | |
# grab the elements we care about | |
ridDomain=${elements[5]} | |
ridUser=${elements[7]} | |
# Now we're going to use the first 9 bits of the domain rid followed by the | |
# first 22 bits of the user rid to make a single 31 bit integer (32-bit signed) | |
# that will be the new unique UID value for this SID | |
let "ridDomain = ($ridDomain & 0x1ff) << 22" | |
let "ridUser = ($ridUser & 0x3fffff)" | |
let "uid = $ridDomain + $ridUser" | |
echo $uid | |
} | |
# grab SIDs from file in first argument or stdin | |
while read sid; do | |
SIDtoUID $sid | |
done < "${1:-/dev/stdin}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment