windows源码分析(14)-权限管理篇
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
windows源码分析(14)-权限管理篇Windows系统是支持多用户的。每个文件可以设置一个访问控制表(即ACL),在ACL中规定每个用户、每个组对该文件的访问权限。不过,只有Ntfs文件系统中的文件才支持ACL。
(Ntfs文件系统中,每个文件的ACL是作为文件的一个附加属性保存在文件中的)。不仅ntfs文件支持ACL机制,每个内核对象也支持ACL,不过内核对象的ACL保存在对象头部的安全属性字段中,只存在于内存,对象一销毁,ACL就跟着销毁。因此,内核对象的ACL是临时的,文件的ACL则是永久保存在磁盘上的。文件的ACL由文件的创建者设置后保存在文件中,以后只有创建者和管理员才可以修改ACL,内核对象的ACL由对象的创建者在创建时指定。
Windows系统中为每个用户、组、机器指定了一个ID,叫SID。每个用户登录到系统后,每当创建一个进程时,就会为进程创建一个令牌(进程的令牌叫主令牌),该令牌包含了用户、组、特权信息。由于子进程在创建时会继承父进程的令牌,所以一个用户创建的所有进程的令牌都是一样的,包含着相同的用户、组、特权等其他信息,只是令牌ID不同而已。换个角度看,令牌实际上相当于用户身份,进程要访问对象时,就出示它的令牌让系统检查,向系统表明自己是谁,在哪几个组中。
这样,当有了令牌和ACL后,当一个进程(准确说是线程)要访问一个对象时,系统就会检查该进程的令牌,申请的访问权限,然后与ACL比较,看看是否满足权限,不满足的话就拒绝访问。
下面我们看看相关的数据结构
typedef struct _SID { //用户ID、组ID、机器ID
UCHAR Revision;//版本号
UCHAR SubAuthorityCount;//RID数组元素个数,即ID级数,最大支持8级SID_IDENTIFIER_AUTHORITY IdentifierAuthority;//该ID的签发机关,6B长ULONG SubAuthority[ANYSIZE_ARRAY];//RID数组,即N级ID
} SID, *PISID;
一个ID就像一个文件路径一样,由签发机关 + N级ID组成。
Windows中有几种预定义的签发机关
#define SECURITY_NULL_SID_AUTHORITY {0,0,0,0,0,0} #define SECURITY_WORLD_SID_AUTHORITY {0,0,0,0,0,1} //世界签发机关 #define SECURITY_LOCAL_SID_AUTHORITY {0,0,0,0,0,2} //本机签发机关 #define SECURITY_CREATOR_SID_AUTHORITY {0,0,0,0,0,3}
#define SECURITY_NON_UNIQUE_AUTHORITY {0,0,0,0,0,4} #define SECURITY_NT_AUTHORITY {0,0,0,0,0,5} //NT域签发机关 #define
SECURITY_RESOURCE_MANAGER_AUTHORITY {0,0,0,0,0,9}
typedef struct _TOKEN
{
TOKEN_SOURCE TokenSource;
LUID TokenId; 令牌ID
LUID AuthenticationId;
LUID ParentTokenId;
LARGE_INTEGER ExpirationTime; 过期时间
struct _ERESOURCE *TokenLock;
SEP_AUDIT_POLICY AuditPolicy;
LUID ModifiedId;
ULONG SessionId;
ULONG UserAndGroupCount; 含有的用户、组总数
ULONG RestrictedSidCount;
ULONG PrivilegeCount; 含有的特权数量
ULONG VariableLength;
ULONG DynamicCharged;
ULONG DynamicAvailable;
ULONG DefaultOwnerIndex; 令牌的默认拥有者在UserAndGroups数组中的位置
PSID_AND_ATTRIBUTES UserAndGroups; 关键。包含的一个用户、N个组(一个‘数组’)
PSID_AND_ATTRIBUTES RestrictedSids;
PSID PrimaryGroup; 令牌的基本组ID(即拥有者所属的基本组)
PLUID_AND_ATTRIBUTES Privileges; 关键。包含的特权
PULONG DynamicPart;
PACL DefaultDacl;
TOKEN_TYPE TokenType; 令牌类型(自己的/模拟的)
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; 模拟级别
ULONG TokenFlags;
BOOLEAN TokenInUse; 是否已被指派成了某个进程的令牌
PVOID ProxyData;
PVOID AuditData;
LUID OriginatingLogonSession;
ULONG VariablePart;
} TOKEN, *PTOKEN;
一个令牌最重要的信息便是它所包含的【特权、用户、组】
下面的函数用于创建一个SID
NTSTATUS
RtlAllocateAndInitializeSid(PSID_IDENTIFIER_AUTHORITY IdentifierAuthority,//签发机关
UCHAR SubAuthorityCount,//级数
ULONG SubAuthority0,
ULONG SubAuthority1,
ULONG SubAuthority2,
ULONG SubAuthority3,
ULONG SubAuthority4,
ULONG SubAuthority5,
ULONG SubAuthority6,
ULONG SubAuthority7,
PSID *Sid) //返回
{
PISID pSid;
if (SubAuthorityCount > 8)
return STATUS_INVALID_SID;
pSid =
RtlpAllocateMemory(RtlLengthRequiredSid(SubAuthorityCount),TAG_SID);
pSid->Revision = SID_REVISION;//固定为1
pSid->SubAuthorityCount = SubAuthorityCount;//级数