SDDL格式中SID的最大长度是多少?

20

我正在将Active Directory身份验证集成到我的应用程序中,并计划将我的应用程序内部帐户与用户的域SID关联起来。 对于我来说,使用SID的字符串格式比使用字节数组更容易处理,因此我计划将其以字符串形式存储在数据库中。 我应该将该字段设多长以确保SID不会被截断?

4个回答

35
我有同样的问题,我相信正确的答案是:
  • ID作为字符串:184个字符或SQL Server中的varchar(184)
  • SID作为十六进制数的字符串:136个字符或SQL Server中的varchar(136)
  • SID作为二进制数据:68字节或SQL Server中的varbinary(68)
我没有亲自检查过这个数学技巧,但这里使用的技术看起来是有效的: https://groups.google.com/d/msg/microsoft.public.dotnet.security/NpIi7c2Toi8/31SVhcepY58J 请参考Russell Mangel于2006年8月19日编写的程序,以下是该程序的副本:

所以我的问题的答案是:

varbinary(68)-- 纯二进制
varchar(136) -- (68*2) = 十六进制字符串
varchar(184) -- SID字符串

我写了一个小程序进行测试,注意.NET 2.0具有SecurityIdentifier.MaxBinaryLength,我不知道这一点。

Console.WriteLine("SID Min. num Bytes: {0}",
SecurityIdentifier.MinBinaryLength);
Console.WriteLine("SID Max. num Bytes: {0}",
SecurityIdentifier.MaxBinaryLength);
Byte[] bytes = new byte[SecurityIdentifier.MaxBinaryLength];
for (Int32 i = 0; i < bytes.Length; i++)
{
    bytes[i] = 0xFF;
}
bytes[0] = 0x01; // Must be 1
bytes[1] = 0x0F; // Max 15 (base10)
SecurityIdentifier sid = new SecurityIdentifier(bytes, 0);
String sidString = sid.ToString();
Console.WriteLine("Max length of SID in String format: {0} ", sidString.Length);
Console.WriteLine(sidString);

结果

SID Min. num Bytes: 8
SID Max. num Bytes: 68
Max length of SID in String format: 184
S-1-281474976710655-4294967295-4294967295-4294967295-4294967295-4294967295-
  4294967295-4294967295-4294967295-4294967295-4294967295-4294967295-
  4294967295-4294967295-4294967295-4294967295 

你能解释一下为什么SQL的SUSER_SID返回VARBINARY(85)而不是(68)吗? - filimonic

2
根据 ntseapi_x.h 文件:
typedef struct _SID_IDENTIFIER_AUTHORITY {
    UCHAR Value[6];
} SID_IDENTIFIER_AUTHORITY, *PSID_IDENTIFIER_AUTHORITY; 

typedef struct _SID {
   UCHAR Revision;
   UCHAR SubAuthorityCount;
   SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
   ULONG SubAuthority[ANYSIZE_ARRAY];
} SID, *PISID;
    
#define SID_MAX_SUB_AUTHORITIES          (15)

UCHAR实际上是一个1字节的unsigned charULONG是一个4字节的unsigned long

SID的最大数据大小为68个字节:UCHAR + UCHAR + (UCHAR * 6) + (ULONG * 15) = 1 + 1 + 6 + 60 = 68

将SID转换为字符串,就像调用ConvertSidToStringSid一样,可能看起来像这样:L"S-1-5-21-66"

  • "S-1" <= 所有SID的起始点
    • 3个字符
  • "5" <= 标识符的权限
    • 数字通常以十进制打印。唯一的例外是如果权限大于4个字节,则以十六进制打印,例如0x1234...
    • 所以最大值将是“4294967296”或“0xffffffffffff”或14个字符
  • "21" & "66" <= 是子权限
    • 每个都可以达到“4294967296”或10个字符,最多15个子权限
  • 各部分由“-”分隔

SID的最大字符串长度为184:3 + 1 + 14 + 1 +(10 * 15)+ 14 = 183,或者计算空值为184。

您可以考虑只使用MAX_UNICODE_STACK_BUFFER_LENGTH或256,这在内存中非常适合。


1

1
  1. 对于字符串格式,第184个常见答案是不正确的。如果权限位于32位和48位之间,则必须表示为十六进制字符串,而不是十进制,并以“0x”开头。这意味着,代表最大48位十进制数所需的15个字符的字符串,实际上需要一个(48位/4位+2)14个字符的字符串,这意味着(184-15+14)需要183个字符来表示整个SID字符串。对于小于32位的情况,使用十进制格式(最多10个十进制字符)。

1
有趣的是,甚至一些微软自己的代码也不遵循这个规则。.NET Security.Principal.SecurityIdentifier构造函数接受十六进制格式,但ToString()方法始终以十进制输出。 - Chalky

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接