CLR 中代码访问安全检测实现原理(5)
值得注意的是,当安全描述符被标记为完全可信任 (SecurityDescriptor::IsFullyTrusted())、堆栈遍历参数指定非受限模式 (IUnrestrictedPermission)、以及 Assembly 是系统 BCL 类库(mscorlib.dll) 或 AppDomain 是缺省 AppDomain (用于加载 BCL 类库,具体说明参见《用WinDbg探索CLR世界 [6] AppDomain 的创建过程 》一文),则忽略 CAS 检测。
对完全可信任概念的含义,可以参考《可怕的 Fully Trusted Code》一文。
如果需要进行 CAS 检测,则 CheckGrants 函数 (ComCodeAccessSecurityEngine.cpp:128) 将完成权限的验证工作。而其实际工作,则将通过 Managed 方法 CodeAccessSecurityEngine::CheckHelper 方法 (CodeAccessSecurityEngine.cs:230) 完成。而 CheckHelper 方法将通过权限类型本身的 IsSubsetOf/Intersect 等方法的实现,来判断 Assembly/AppDomain 现有权限集,是否包括请求的权限。而 Assembly/AppDomain 现有权限集,则是在 Assembly 被载入以及 AppDomain 被创建时,由 CLR Loader 创建的。以后有机会再专门写篇文章分析这个权限集的构建逻辑。
以下内容为程序代码:
private static void CheckHelper(PermissionSet grantedSet, PermissionSet deniedSet, CodeAccessPermission demand, PermissionToken permToken)
{
if (permToken == null)
permToken = PermissionToken.GetToken(demand);
try
{
// 获取权限集不能为空
if (grantedSet == null)
{
throw new SecurityException(...);
}
// 不处理权限集不受限或请求权限为非受限权限的情况
else if (!grantedSet.IsUnrestricted() || !(demand is IUnrestrictedPermission))
{
CodeAccessPermission grantedPerm = (CodeAccessPermission)grantedSet.GetPermission(permToken);
if (grantedPerm == null)
{
if (!demand.IsSubsetOf( null ))
throw new SecurityException(String.Format(...);
else
return;
}
}
// 验证权限没有被显式禁止
if (deniedSet != null)
{
CodeAccessPermission deniedPerm = (CodeAccessPermission)deniedSet.GetPermission(permToken);
if (deniedPerm != null)
{
if (deniedPerm.Intersect(demand) != null)
{
throw new SecurityException(...);
}
}
}
}
catch (Exception e)
{
// 所有的非 SecurityException 异常将都被转换为 SecurityException 异常
// 因为这些异常的发生都是因为获取指定权限操作失败的原因
if (e is SecurityException)
throw e;
else
throw new SecurityException(...);
}
}
最后 CodeAccessCheckStackWalkCB 还需要处理显式指定了安全对象帧的情况。对帧安全对象进行检测的 CheckFrameData 方法 (ComCodeAccessSecurityEngine.cpp:231) 与 CheckGrants 类似,也是最终通过 CheckHelper 方法实现的,这里就不罗嗦了。堆栈帧的安全对象,等到介绍堆栈结构的时候再详细解释。
至此,CLR 中代码访问安全检测的大致实现思路以及比较清晰了,等把堆栈帧结构和 CLR Loader 安全权限集构建的文章弄完,再整理篇完整的,呵呵。
Tags:
作者:郁郁小蝎评论内容只代表网友观点,与本站立场无关!
评论摘要(共 0 条,得分 0 分,平均 0 分)
查看完整评论