安全标识符
Windows 使用安全标识符 (SID) 作为最终值来区分安全实体。 例如,为系统上的单个用户创建的每个新帐户分配唯一的安全标识符。 对于文件系统,仅使用此 SID。
下图说明了安全标识符结构。
除了唯一的 SID,Windows 系统还定义了一组已知的标识符。 例如,本地管理员是一个已知的 SID。
Windows 提供了一种内核内机制,用于在内核环境中在 SID 和用户名之间进行转换。 这些函数调用可从 ksecdd 驱动程序获取,该驱动程序使用用户模式帮助程序服务实现这些函数。 因此,在文件系统中使用它们必须遵守与用户模式服务通信的通常规则。 这些调用不能在分页文件 I/O 期间使用。
其中一些函数包括:
SecMakeSPN 创建一个服务提供商名称字符串,可在与特定安全服务提供商通信时使用。
SecMakeSPNEx 是 Windows XP 中引入的 SecMakeSPN 的增强版本。
SecMakeSPNEx2 是从 Windows Vista 和 Windows Server 2008 开始提供的 SecMakeSPNEx 的增强版本。
SecLookupAccountSid 返回指定 SID 的帐户名称。
SecLookupAccountName 检索指定帐户名称的 SID。
SecLookupWellKnownSid 返回指定的已知 SID 类型的正确 SID。 此功能在 Windows Server 2003 及更高版本上可用。
此外,任何内核驱动程序都可以使用以下标准运行时库例程创建 SID:
RtlInitializeSid 为新 SID 初始化缓冲区。
RtlLengthSid 确定存储在给定缓冲区中的 SID 的大小。
RtlValidSid 确定给定的 SID 缓冲区是否为有效的格式化缓冲区。
RtlLengthSid 和 RtlValidSid 假定存在 SID 的 8 字节固定标头。 因此,在调用这些函数之前,驱动程序应检查 SID 标头的最小长度。
虽然还有其他几个 RTL 函数,但此列表提供了构造 SID 时所需的主要函数。
下面的代码示例演示如何为“本地系统”实体创建 SID。 还可以使用 Windows Server 2003 中引入的更简单的 SecLookupWellKnownSid 函数。
{
//
// temporary stack-based storage for an SID
//
UCHAR sidBuffer[128];
PISID localSid = (PISID) sidBuffer;
SID_IDENTIFIER_AUTHORITY localSidAuthority =
SECURITY_NT_AUTHORITY;
//
// build the local system SID
//
RtlZeroMemory(sidBuffer, sizeof(sidBuffer));
localSid->Revision = SID_REVISION;
localSid->SubAuthorityCount = 1;
localSid->IdentifierAuthority = localSidAuthority;
localSid->SubAuthority[0] = SECURITY_LOCAL_SYSTEM_RID;
//
// make sure it is valid
//
if (!RtlValidSid(localSid)) {
DbgPrint("no dice - SID is invalid\n");
return(1);
}
}
下面的代码示例演示如何使用“本地系统”实体的 SecLookupWellKnownSid 函数创建 SID:
{
UCHAR sidBuffer[128];
PISID localSid = (PISID) sidBuffer;
SIZE_T sidSize;
status = SecLookupWellKnownSid(WinLocalSid,
&localSid,
sizeof(sidBuffer),
&sidSize);
if (!NT_SUCCESS(status)) {
//
// error handling
//
}
}
这两种方法都是有效的,但后一种代码是首选。 这些代码示例使用本地缓冲区来存储 SID。 这些缓冲区不能在当前调用上下文之外使用。 如果 SID 缓冲区需要持久化,则应从池内存中分配缓冲区。