sergey vasin

The IT blog

ConvertFrom-sthSID — функция для конвертации строки SID в формат массива байтов

leave a comment »

В предыдущей статье мы говорили о преобразовании SID из массива байтов в строчный формат. Почему бы нам не написать функцию для обратного преобразования.

Назовем ее ConvertFrom-sthSID.

function ConvertFrom-sthSID
{

}

Начнем с определения параметра. В качестве его имени мы выберем SID, его использование будет обязательным, и, так же как и в предыдущем случае, мы не будем против если пользователи этой функции решат передать исходную строку SID по конвейеру.

В качестве типа данных мы используем [string[]], что позволяет указать в качестве значения параметра массив строк. Опять же, если это как-либо пригодится пользователю функции, мы не будем препятствовать.

function ConvertFrom-sthSID
{
    Param(
        [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
        [string[]]
        $SID
    )
}

Так как мы реализуем возможность использования конвейера для передачи функции строк SID, нам потребуется использование блока process. Отличие от предыдущей функции, ConvertTo-sthSID, состоит в том, что в данном случае нам не понадобятся блоки begin и end. Все необходимые преобразования будут происходить в блоке process.

function ConvertFrom-sthSID
{
    Param(
        [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
        [string[]]
        $SID
    )

    process
    {

    }
}

Для того, чтобы не прописывать отдельный код для конвертации строк, полученных с использованием параметра -SID, и строк, переданных посредством конвейера, воспользуемся конструкцией foreach.

В данном случае, при использовании параметра -SID, переменная $SID будет содержать весь массив строк (как вы помните, мы разрешили в качестве значения параметра $SID указывать массив) и использование foreach позволит обработать их одну за другой.

Если же для передачи исходных данных был использован конвейер, то блок process будет выполнен столько раз, сколько элементов было передано по конвейеру. И каждый раз переменная $SID будет содержать одну, обрабатываемую в данных момент времени, строку SID. В этом случае foreach отнесется к ней как к массиву из одного элемента и позволит произвести с ней те же самые действия.

function ConvertFrom-sthSID
{
    Param(
        [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
        [string[]]
        $SID
    )

    process
    {
        foreach ($s in $SID)
        {

        }
    }
}

Далее нам нужно разделить строку на элементы. Сделаем мы это при помощи оператора -split. По умолчнию с качестве разделителя используется символ пробела, поэтом нам потребуется явно указать, что в качестве символа разделения будет использован дефис.

Кроме того, как мы знаем, первым элементом является буква ‘S’. Для дальнейшей обработки она нам не понадобится, поэтому можно ее пропустить, что мы и сделаем при помощи командлета Select-Object и параметра -Skip.

Кроме того, определим переменную $Result, в которой будет содержаться результат наших преобразований, в качестве массива.

function ConvertFrom-sthSID
{
    Param(
        [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
        [string[]]
        $SID
    )

    process
    {
        foreach ($s in $SID)
        {
            $SIDSplitted = $s -split '-' | Select-Object -Skip 1

            $Result = @()
        }
    }
}

Далее, так же как и в прошлый раз, для получения информации о структуре SID мы обратимся к сайту MSDN — https://msdn.microsoft.com/en-us/library/cc230371.aspx.

Мы знаем, что первая цифра обозначает Revision, и в форме массива байтов она расположена в самом первом элементе.

function ConvertFrom-sthSID
{
    Param(
        [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
        [string[]]
        $SID
    )

    process
    {
        foreach ($s in $SID)
        {
            $SIDSplitted = $s -split '-' | Select-Object -Skip 1

            $Result = @()

            # Revision
            $Result += [byte]$SIDSplitted[0]
        }
    }
}

Затем в массиве байтов указывается количество четырехбайтовых блоков SubAuthority. Учитывая, что в переменной $SIDSplitted кроме них находятся блоки Revision и IdentifierAuthority, количество блоков SubAuthority мы можем получить вычтя 2 из общего количества элементов массива переменной $SIDSplitted.

function ConvertFrom-sthSID
{
    Param(
        [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
        [string[]]
        $SID
    )

    process
    {
        foreach ($s in $SID)
        {
            $SIDSplitted = $s -split '-' | Select-Object -Skip 1

            $Result = @()

            # Revision
            $Result += [byte]$SIDSplitted[0]

            # SubAuthorityCount
            $Result += [byte]$($SIDSplitted.Count - 2)
        }
    }
}

Далее расположен блок IdentifierAuthority. Состоит он из шести байтов, причем первые пять из них обычно представлены нулями. Значение же шестого байта мы найдем во втором элементе массива переменной $SIDSplitted.

function ConvertFrom-sthSID
{
    Param(
        [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
        [string[]]
        $SID
    )

    process
    {
        foreach ($s in $SID)
        {
            $SIDSplitted = $s -split '-' | Select-Object -Skip 1

            $Result = @()

            # Revision
            $Result += [byte]$SIDSplitted[0]

            # SubAuthorityCount
            $Result += [byte]$($SIDSplitted.Count - 2)

            # IdentifierAuthority
            for ($i = 0; $i -lt 5; $i++)
            {
                $Result += [byte]0
            }
            $Result += [byte]$SIDSplitted[1]
        }
    }
}

Все оставшиеся значения массива, расположенного в переменной $SIDSplitted — это блоки SubAuthority. В формате массива байтов каждый из них представлен в виде четырех байтов, причем младшим байтом является первый, а страшим, соответственно, последний.

Поэтому для конвертации каждого из этих блоков мы воспользуемся конструкцией for.

function ConvertFrom-sthSID
{
    Param(
        [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
        [string[]]
        $SID
    )

    process
    {
        foreach ($s in $SID)
        {
            $SIDSplitted = $s -split '-' | Select-Object -Skip 1

            $Result = @()

            # Revision
            $Result += [byte]$SIDSplitted[0]

            # SubAuthorityCount
            $Result += [byte]$($SIDSplitted.Count - 2)

            # IdentifierAuthority
            for ($i = 0; $i -lt 5; $i++)
            {
                $Result += [byte]0
            }
            $Result += [byte]$SIDSplitted[1]

            # SubAuthority
            for ($i = 2; $i -lt $($SIDSplitted.Count); $i++)
            {

            }
        }
    }
}

Внутри этой конструкции, младший байт мы получаем при помощи оператора -band (что представляет из себя побитовое И) и аргумента 255, второй — точно таким же образом, но предварительно сдвинув исходное значение на 8 бит вправо при помощи оператора -shr, третий — на 16 бит, и четвертый — на 24 бита.

После этого мы возвращаем результат выполнения функции.

function ConvertFrom-sthSID
{
    Param(
        [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
        [string[]]
        $SID
    )

    process
    {
        foreach ($s in $SID)
        {
            $SIDSplitted = $s -split '-' | Select-Object -Skip 1

            $Result = @()

            # Revision
            $Result += [byte]$SIDSplitted[0]

            # SubAuthorityCount
            $Result += [byte]$($SIDSplitted.Count - 2)

            # IdentifierAuthority
            for ($i = 0; $i -lt 5; $i++)
            {
                $Result += [byte]0
            }
            $Result += [byte]$SIDSplitted[1]

            # SubAuthority
            for ($i = 2; $i -lt $($SIDSplitted.Count); $i++)
            {
                $Result += [byte]$($SIDSplitted[$i] -band 255)
                $Result += [byte]$(($SIDSplitted[$i] -shr 8) -band 255)
                $Result += [byte]$(($SIDSplitted[$i] -shr 16) -band 255)
                $Result += [byte]$(($SIDSplitted[$i] -shr 24) -band 255)
            }

            return $Result
        }
    }
}

Полный текст функции:

function ConvertFrom-sthSID
{
    Param(
        [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
        [string[]]
        $SID
    )

    process
    {
        foreach ($s in $SID)
        {
            $SIDSplitted = $s -split '-' | Select-Object -Skip 1

            $Result = @()

            # Revision
            $Result += [byte]$SIDSplitted[0]

            # SubAuthorityCount
            $Result += [byte]$($SIDSplitted.Count - 2)

            # IdentifierAuthority
            for ($i = 0; $i -lt 5; $i++)
            {
                $Result += [byte]0
            }
            $Result += [byte]$SIDSplitted[1]

            # SubAuthority
            for ($i = 2; $i -lt $($SIDSplitted.Count); $i++)
            {
                $Result += [byte]$($SIDSplitted[$i] -band 255)
                $Result += [byte]$(($SIDSplitted[$i] -shr 8) -band 255)
                $Result += [byte]$(($SIDSplitted[$i] -shr 16) -band 255)
                $Result += [byte]$(($SIDSplitted[$i] -shr 24) -band 255)
            }

            return $Result
        }
    }
}

Мы можем использовать функцию следующим образом:

ConvertFrom-sthSID -SID S-1-5-21-1234567890-1234567890-1234567890-1234

или так:

'S-1-5-21-1234567890-1234567890-1234567890-1234' | ConvertFrom-sthSID

Эта функция является частью модуля sthLDAPTools, который вы можете установить из PowerShell Gallery при помощи следующей команды:

Install-Module -Name sthLDAPTools

Все модули доступны по следующей ссылке:
https://sergeyvasin.net/modules/


Страницы в социальных сетях:

Twitter: https://twitter.com/vsseth
Facebook: https://fb.com/inpowershell
VKontakte: https://vk.com/inpowershell


Реклама

Written by Сергей Васин

Сентябрь 6, 2017 в 12:54

Опубликовано в Active Directory, PowerShell

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s