在C#中从Active Directory添加所有用户SID

时间:2017-11-09 18:50:34

标签: c# active-directory

我有一个问题无法将所有Sid添加到我当前的循环中。其他一切都按照我的预期运作。我只需要帮助添加我的代码,为我的代码显示的每个用户添加SID。 SID现在将显示。

新的错误讯息: enter image description here

这是我目前的代码:

 namespace ActiveDirectoryDisplayNamesApp
{
    class Program
    {
        static void Main(string[] args)
        {

            using (var context = new PrincipalContext(ContextType.Domain, "nor-amcoldcorp.local"))
            {
                using (var searcher = new PrincipalSearcher(new UserPrincipal(context)))
                {
                    foreach (var result in searcher.FindAll())
                    {
                        DirectoryEntry de = result.GetUnderlyingObject() as DirectoryEntry;
                        var sidByte = ObjectToByteArray(de.Properties["objectSId"].Value);
                        Console.WriteLine("First Name: " + de.Properties["givenName"].Value);
                        Console.WriteLine("Last Name : " + de.Properties["sn"].Value);
                        Console.WriteLine("SAM account name   : " + de.Properties["samAccountName"].Value);
                        Console.WriteLine("User principal name: " + de.Properties["userPrincipalName"].Value);
                        Console.WriteLine("Object Sid: " + System.Text.Encoding.UTF8.GetString(sidByte)); //Here is the changement
                        Console.WriteLine();
                    }
                }
            }
            Console.ReadLine();

        }

        static public byte[] ObjectToByteArray(Object obj)
        {
            if (obj == null)
                return null;

            BinaryFormatter bf = new BinaryFormatter();
            MemoryStream ms = new MemoryStream();
            bf.Serialize(ms, obj);

            return ms.ToArray();
        }






    }
}

4 个答案:

答案 0 :(得分:0)

编辑:

声明此功能:

private byte[] ObjectToByteArray(Object obj)
    {
        if(obj == null)
            return null;

        BinaryFormatter bf = new BinaryFormatter();
        MemoryStream ms = new MemoryStream();
        bf.Serialize(ms, obj);

        return ms.ToArray();
    }

要做到这一点:

byte[] bytes = Encoding.Default.GetBytes(de.Properties["objectSid"].value);
sidByte= Encoding.UTF8.GetString(bytes);

Console.WriteLine("Object Sid: " + sidByte ); //Here is the changement 

或者你尝试这个approcah(如果第一个没有用)但保留第一个将你的字节对象转换为byte的函数:

声明一个函数

static string BytesToStringConverted(byte[] bytes)
{
    using (var stream = new MemoryStream(bytes))
    {
        using (var streamReader = new StreamReader(stream))
        {
            return streamReader.ReadToEnd();
        }
    }
}

比如那样称呼:

Console.WriteLine("Object Sid: " +BytesToStringConverted (sidByte)

答案 1 :(得分:0)

de.Properties["objectSid"].value返回一个Byte []数组,以查看您需要将其解析为字符串以获取您正在寻找的功能的SID。可以找到关于如何做到这一点的好帖子here

以下是将数组转换为可用字符串所需的函数:

public static string ConvertByteToStringSid(Byte[] sidBytes)
{
    StringBuilder strSid = new StringBuilder();
    strSid.Append("S-");
    try
    {
        // Add SID revision.
        strSid.Append(sidBytes[0].ToString());
        // Next six bytes are SID authority value.
        if (sidBytes[6] != 0 || sidBytes[5] != 0)
        {
            string strAuth = String.Format
                ("0x{0:2x}{1:2x}{2:2x}{3:2x}{4:2x}{5:2x}",
                (Int16)sidBytes[1],
                (Int16)sidBytes[2],
                (Int16)sidBytes[3],
                (Int16)sidBytes[4],
                (Int16)sidBytes[5],
                (Int16)sidBytes[6]);
            strSid.Append("-");
            strSid.Append(strAuth);
        }
        else
        {
            Int64 iVal = (Int32)(sidBytes[1]) +
                (Int32)(sidBytes[2] << 8) +
                (Int32)(sidBytes[3] << 16) +
                (Int32)(sidBytes[4] << 24);
            strSid.Append("-");
            strSid.Append(iVal.ToString());

        // Get sub authority count...
        int iSubCount = Convert.ToInt32(sidBytes[7]);
        int idxAuth = 0;
        for (int i = 0; i < iSubCount; i++)
        {
            idxAuth = 8 + i * 4;
            UInt32 iSubAuth = BitConverter.ToUInt32(sidBytes, idxAuth);
            strSid.Append("-");
            strSid.Append(iSubAuth.ToString());
        }
    }
    catch (Exception ex)
    {

    }
    return strSid.ToString();
}

以下是调用该函数所需的内容:

System.DirectoryServices.PropertyCollection coll = de.Properties;
object obVal = coll["objectSid"].Value;
string yourSID;
if (null != obVal)
{
    yourSID = ConvertByteToStringSid((Byte[])obVal);
}

答案 2 :(得分:0)

已经有一个专用的Sid类,可用于解码Sid数据。

var sidBytes = (byte[])de.Properties["objectSId"].Value;
var sid = new SecurityIdentifier(sidBytes ,0);
string strSid = sid.Value;//Something like S-1-5-21..

答案 3 :(得分:0)

  1. 对于十六进制形式,应该是:string strAuth = String.Format("0x{0:x2}{1:x2}{2:x2}{3:x2}{4:x2}{5:x2}",

  2. 对于 .NET 5,SecurityIdentifier 仅适用于 Windows。 https://github.com/dotnet/runtime/blob/6bc6560e51d1cf58b54561f7be44801864479b8d/src/libraries/System.Security.Principal.Windows/src/System/Security/Principal/SID.cs#L403-L478

  3. 发现原版的一些错误

<块引用>

https://www.codeproject.com/articles/3688/how-to-get-user-sid-using-directoryservices-classe

公共静态字符串 ConvertByteToStringSid(Byte[] sidBytes)

  • 十六进制转换(错误 "0x{0:2x}{1:2x}{2:2x}{3:2x}{4:2x}{5:2x}",正确:"0x{0:x2}{1:x2}{2:x2}{3:x2}{4:x2}{5:x2}"
  • 第二个字节的子权限计数,而不是第 8 个字节(错误 Convert.ToInt32(sidBytes[7]),正确:Convert.ToInt32(sidBytes[1])

我遵循了原始实现并与类 SecurityIdentifier 的结果进行了比较,还考虑了注释:

<块引用>

SID 解码错误 Pin

你好, 我认为您的 SID 解码是错误的。子权限的数量是 SID 字节数组中的第 2 个字节,而不是第 8 个,并且主权限的字节存储顺序与您正在读取的顺序不同。

我想分享一个更好的版本,可以在以下位置找到: https://gist.github.com/thohng/8820153f7d1e107b6619b34fd765f887

public static string ConvertByteToStringSid(byte[] sidBytes)
{
    if (sidBytes == null || sidBytes.Length < 8 ||
        sidBytes.Length > 68)   // maximum 15 sub authorities
        return string.Empty;

    var span = new ReadOnlySpan<byte>(sidBytes);

    var strSid = new StringBuilder("S-");

    // Add SID revision.
    strSid.Append(span[0]);

    // Get sub authority count...
    var subAuthoritiesLength = Convert.ToInt32(span[1]);
    if (sidBytes.Length != 8 + subAuthoritiesLength * 4)
        return string.Empty;

    long identifierAuthority =
        (((long)span[2]) << 40) +
        (((long)span[3]) << 32) +
        (((long)span[4]) << 24) +
        (((long)span[5]) << 16) +
        (((long)span[6]) << 8) +
        span[7];
    strSid.Append('-');
    strSid.Append(identifierAuthority);

    span = span[8..];

    for (int i = 0; i < subAuthoritiesLength; i++, span = span[4..])
    {
        strSid.Append('-');
        strSid.Append(BitConverter.ToUInt32(span.Slice(0, 4)));
    }

    return strSid.ToString();
}

和单元测试:

private static Func<byte[], string> GetConvertByteToStringSidService() => LdapHelper.ConvertByteToStringSid;

[Fact]
public void ConvertByteToStringSid_Builtin()
{
    var service = GetConvertByteToStringSidService();
    var sid = new byte[] { 1, 2, 0, 0, 0, 0, 0, 5, 32, 0, 0, 0, 39, 2, 0, 0 };
    var result = service(sid);
    Assert.Equal("S-1-5-32-551", result);
}

[Fact]
[SupportedOSPlatform("windows")]
public void ConvertByteToStringSid_Builtin_Windows()
{
    var sid = new byte[] { 1, 2, 0, 0, 0, 0, 0, 5, 32, 0, 0, 0, 39, 2, 0, 0 };
    var s2 = new SecurityIdentifier(sid, 0);
    Assert.Equal("S-1-5-32-551", s2.ToString());
}

[Fact]
public void ConvertByteToStringSid_Malformed()
{
    var service = GetConvertByteToStringSidService();

    var sid1 = new byte[] { 1, 5, 0, 0, 0, 0, 0, 5, 21, 0, 0, 0, 222, 206, 60, 4, 227, 115, 59, 3, 168, 94, 83, 2, 1, 4, 0, 0, 1 };
    var result1 = service(sid1);
    Assert.Equal("", result1);

    var sid2 = new byte[] { 1, 5, 0, 0, 0, 0, 0, 5, 21, 0, 0, 0, 222, 206, 60, 4, 227, 115, 59, 3, 168, 94, 83, 2, 1, 4, 0 };
    var result2 = service(sid2);
    Assert.Equal("", result2);

    var sid3 = new byte[] { 1, 4, 0, 0, 0, 0, 0, 5, 21, 0, 0, 0, 222, 206, 60, 4, 227, 115, 59, 3, 168, 94, 83, 2, 1, 4, 0, 0 };
    var result3 = service(sid3);
    Assert.Equal("", result3);
}

[Fact]
public void ConvertByteToStringSid_Max()
{
    var service = GetConvertByteToStringSidService();

    var sid = new byte[] { 1, 1, 255, 254, 253, 252, 0, 0, 251, 250, 249, 248 };
    var result = service(sid);
    Assert.Equal("S-1-281470647926784-4177132283", result);

    var sid2 = new byte[] { 1, 5, 136, 0, 44, 89, 0xFE, 5, 21, 0, 0, 0, 222, 206, 60, 4, 227, 115, 59, 3, 168, 94, 83, 2, 1, 4, 0, 0 };
    var result2 = service(sid2);
    Assert.Equal("S-1-149534325472773-21-71093982-54227939-39018152-1025", result2);
}

[Fact]
[SupportedOSPlatform("windows")]
public void ConvertByteToStringSid_Max_Windows()
{
    var sid = new byte[] { 1, 1, 255, 254, 253, 252, 0, 0, 251, 250, 249, 248 };
    var s1 = new SecurityIdentifier(sid, 0);
    Assert.Equal("S-1-281470647926784-4177132283", s1.ToString());

    var sid2 = new byte[] { 1, 5, 136, 0, 44, 89, 0xFE, 5, 21, 0, 0, 0, 222, 206, 60, 4, 227, 115, 59, 3, 168, 94, 83, 2, 1, 4, 0, 0 };
    var s2 = new SecurityIdentifier(sid2, 0);
    Assert.Equal("S-1-149534325472773-21-71093982-54227939-39018152-1025", s2.ToString());
}

[Fact]
public void ConvertByteToStringSid_NullEmpty()
{
    var service = GetConvertByteToStringSidService();

    var sid1 = Array.Empty<byte>();
    var result1 = service(sid1);
    Assert.Equal("", result1);

    var result2 = service(null);
    Assert.Equal("", result2);
}

[Fact]
public void ConvertByteToStringSid_Success()
{
    var service = GetConvertByteToStringSidService();
    var sid = new byte[] { 1, 5, 0, 0, 0, 0, 0, 5, 21, 0, 0, 0, 222, 206, 60, 4, 227, 115, 59, 3, 168, 94, 83, 2, 1, 4, 0, 0 };
    var result = service(sid);
    Assert.Equal("S-1-5-21-71093982-54227939-39018152-1025", result);
}

[Fact]
[SupportedOSPlatform("windows")]
public void ConvertByteToStringSid_Windows()
{
    var sid = new byte[] { 1, 5, 0, 0, 0, 0, 0, 5, 21, 0, 0, 0, 222, 206, 60, 4, 227, 115, 59, 3, 168, 94, 83, 2, 1, 4, 0, 0 };
    var s1 = new SecurityIdentifier(sid, 0);
    Assert.Equal("S-1-5-21-71093982-54227939-39018152-1025", s1.ToString());
}