我想将 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
看一下 SecurityIdentifier 类。 然后你可以做一些简单的事情,比如,
var sidInBytes = (byte[]) *somestuff*
var sid = new SecurityIdentifier(sidInBytes, 0);
// This gives you what you want
sid.ToString();
加载directoryEntry中的属性后....
var usrId = (byte[])directoryEntry.Properties["objectSid"][0];
var objectID = (new SecurityIdentifier(usrId,0)).ToString();
这就是我所做的,经过一番阅读后,将值存储在 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();
}
SecurityIdentifier 在 .Net Core 下不可用,但只要您只需要字符串表示形式(又名安全描述符定义语言或 SDDL 字符串),构造起来并不难。
基本上有一个版本号(1 个字节)、一个节数(1 个字节)、一个标识权限(6 个字节)和 1 到 5 个子权限(每个 4 个字节)。
我创建了一个 github 存储库,其中基于 CodeProject 文章进行了单元测试,并在将其翻译为 VB 后添加了一个基于 Miro Mannino 的 gist 的转换器。翻译成 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
我使用的是 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));
}
}