如何将.net中的SID转换为字符串

问题描述 投票:0回答:5

我想将 SID 的 System.Byte[] 类型转换为 String。

我的代码:

string path = "LDAP://DC=abc,DC=contoso,DC=com";
DirectoryEntry entry = new DirectoryEntry(path);
DirectorySearcher mySearcher = new DirectorySearcher(entry);

mySearcher.Filter = "(&(objectClass=user)(samaccountname=user1))";
results = mySearcher.FindAll();
foreach (SearchResult searchResult in results)
{
    Console.WriteLine(searchResult.Properties["ObjectSID"][0].ToString());
}

我尝试过这个,但它从我当前登录的域获取值,而我需要从给定的域获取值。

System.Security.Principal.NTAccount(user1)
    .Translate([System.Security.Principal.SecurityIdentifier]).value
c# .net
5个回答
62
投票

看一下 SecurityIdentifier 类。 然后你可以做一些简单的事情,比如,

var sidInBytes = (byte[]) *somestuff*
var sid = new SecurityIdentifier(sidInBytes, 0);
// This gives you what you want
sid.ToString();

2
投票

加载directoryEntry中的属性后....

var usrId = (byte[])directoryEntry.Properties["objectSid"][0];
var objectID = (new SecurityIdentifier(usrId,0)).ToString();

1
投票

这就是我所做的,经过一番阅读后,将值存储在 oct 中似乎更安全。

如果你不知道对方有哪些服务器。

下面的代码展示了如何获得您想要的结果:

private static string ExtractSinglePropertyValueFromByteArray(object value)
{
    //all if checks etc has been omitted
    string propertyValue = string.Empty;
    var bytes = (byte[])value;
    var propertyValueOct = BuildOctString(bytes); // 010500....etc
    var propertyValueSec = BuildSecString(bytes); // S-1-5-...etc
    propertyValue = propertyValueSec;
    return propertyValue;
}

private static string BuildSecString(byte[] bytes)
{
    return new SecurityIdentifier(bytes,0).Value.ToString();
}

private static string BuildOctString(byte[] bytes)
{
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < bytes.Length; i++)
    {
        sb.Append(bytes[i].ToString("X2"));
    }
    return sb.ToString();
}

0
投票

SecurityIdentifier 在 .Net Core 下不可用,但只要您只需要字符串表示形式(又名安全描述符定义语言或 SDDL 字符串),构造起来并不难。

基本上有一个版本号(1 个字节)、一个节数(1 个字节)、一个标识权限(6 个字节)和 1 到 5 个子权限(每个 4 个字节)。

我创建了一个 github 存储库,其中基于 CodeProject 文章进行了单元测试,并在将其翻译为 VB 后添加了一个基于 Miro Manninogist 的转换器。翻译成 c# 留给读者作为练习......


    ''' Cribbed from https://gist.github.com/miromannino/04be6a64ea0b5f4d4254bb321e09d628
    ''' where the license was (per a comment from miro):
    ''' The License is: Do Whatever You Want With It 2.0
    ''' aka I don't care, I hope it helps you!
    Private Shared Function GetSid(byteCollection As IEnumerable(Of Byte)) As String

        ' sid[0] is the Revision, we allow only version 1, because it's the
        ' only version that exists right now.
        If byteCollection(0) <> 1 Then Throw New ArgumentOutOfRangeException("SID (bytes(0)) revision must be 1")

        Dim stringSidBuilder = New StringBuilder("S-1-")

        ' The next byte specifies the numbers of sub authorities
        ' (number of dashes minus two), should be 5 or less, but not enforcing that
        Dim subAuthorityCount = byteCollection(1)

        ' IdentifierAuthority (6 bytes starting from the second) (big endian)
        Dim identifierAuthority As Long = 0

        Dim offset = 2
        Dim size = 6
        Dim i As Integer

        For i = 0 To size - 1
            identifierAuthority = identifierAuthority Or CLng(byteCollection(offset + i)) << 8 * (size - 1 - i)
        Next

        stringSidBuilder.Append(identifierAuthority.ToString())

        ' Iterate all the SubAuthority (little-endian)
        offset = 8
        size = 4 ' 32-bits (4 bytes) for each SubAuthority
        i = 0
        While i < subAuthorityCount
            Dim subAuthority As Long = 0

            For j = 0 To size - 1
                ' the below "Or" is a logical Or not a boolean operator
                subAuthority = subAuthority Or CLng(byteCollection(offset + j)) << 8 * j
            Next
            stringSidBuilder.Append("-").Append(subAuthority)
            i += 1
            offset += size
        End While

        Return stringSidBuilder.ToString()
    End Function

0
投票

我使用的是 Linux,因此我无法使用 Microsoft 库。我移植了 @jmoreno 发布的 Visual Basic。

public static string GetSid(IEnumerable<byte> byteCollection)
{
    var byteArray = byteCollection as byte[] ?? byteCollection.ToArray();

    // sid[0] is the Revision, we allow only version 1, because it's the
    // only version that exists right now.
    if (byteArray[0] != 1)
        throw new ArgumentOutOfRangeException(
            nameof(byteCollection),
            "SID (bytes[0]) revision must be 1"
        );

    var stringSidBuilder = new StringBuilder("S-1-");

    // The next byte specifies the numbers of sub authorities
    // (number of dashes minus two), should be 5 or less, but not enforcing that
    var subAuthorityCount = byteArray[1];

    // IdentifierAuthority (6 bytes starting from the second) (big endian)
    long identifierAuthority = 0;
    var offset = 2;
    var size = 6;

    for (var i = 0; i < size; i++)
    {
        identifierAuthority |= (long)byteArray[offset + i] << 8 * (size - 1 - i);
    }
    stringSidBuilder.Append(identifierAuthority);

    // Iterate all the SubAuthority (little-endian)
    offset = 8;
    size = 4; // 32-bits (4 bytes) for each SubAuthority

    for (var i = 0; i < subAuthorityCount; i++)
    {
        long subAuthority = 0;

        for (var j = 0; j < size; j++)
        {
            // the below "Or" is a logical Or not a boolean operator
            subAuthority |= (long)byteArray[offset + j] << 8 * j;
        }

        stringSidBuilder.Append('-').Append(subAuthority);
        offset += size;
    }

    return stringSidBuilder.ToString();
}

我也做了单元测试:

[TestClass]
public class SidConverterTests
{
    [TestMethod]
    public void BytesToStringHappyPathTest()
    {
        IEnumerable<byte> byteCollection = [ 1, 5, 0, 0, 0, 0, 0, 5, 21, 0, 0, 0, 2, 49, 177, 214, 81, 110, 183, 63, 11, 252, 167, 173, 147, 48, 0, 0 ];
        var expected = "S-1-5-21-3601936642-1068985937-2913467403-12435";
        Assert.AreEqual(expected, SidConverter.GetSid(byteCollection));
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.