贝贝花花包包店,精品555皮具,钱夹,皮夹

字体: | 推荐给好友 上一篇 | 下一篇

Windows2000 服务器端应用程序开发设计指南-使用者环境

发布: 2008-5-01 20:40 | 作者: Jeffrey Richter Jaso | 来源: 网络转载 | 查看: 365次

修改权杖资讯
 

大部分的权杖资讯是固定的。例如,您不能设定一位权杖使用者的SID与它所拥有的不同,您也不能增加群组SIDs或权限给权杖。而您可以做的修改属于两类:

  • 可以被调整 的资讯
     
  • 可以被设定 的资讯
     

说明

尽管已经存在的权杖可改变的部份很少,但是以现存的权杖为基础而产生一个增加限制的新权杖是可能的。这种技巧被称为建立一个受限的权杖,在本章稍后有详细的讨论。


设定资讯的处理程序,让它以您能想像的的方法运作。您可以建立一个结构并把它及权杖的handle传递到系统函数中,然后由系统设定权杖中的资讯。

调整资讯与设定资讯的运作有点不同。权杖中的权限及群组都可以有两种状态:即启用及停用。例如,虽然您不能在权杖中「设定」权限清单,但是您可以使已经存在于清单的个别权限启用及停用。

我们最常对权杖做的修改是设定权杖预设的DACL(为了预设的安全性而使用,在前面章节中有描述过),以及调整权杖的权限。您会发现设定权杖之预设拥有者及调整群组的处理程序,分别与设定预设DACL及调整权杖的权限非常类似。

调整权杖的权限
 

在讨论如何调整权杖的权限前,让我们扼要地重述在第九章已经学习过的权限部份,然后再慢慢扩大范围:

  • 权限被分派到信任成员中(使用者及群组)。
     
  • 当使用者登入系统时,使用者的权限会被复制到使用者的权杖中。
     
  • 权限被显示的名称、程序名称及LUID识别。
     

在您可以调整权杖的权限之前,必须知道如何从权限的程序名称中取得系统使用的LUID。这必须经由呼叫LookupPrivilegeValue函数来完成:

BOOL LookupPrivilegeValue( 

LPCTSTR lpSystemName,
LPCTSTR lpName,
PLUID lpLuid);

您应该传递一个字串给lpSystemName参数,这个字串代表您想要收到LUID的系统名称。传递NULL以指出本地端机器。lpName参数则指出系统权限的程序名称,您应该传递出自《Platform SDK》的#define(例如,SE_TCB_NAME或SE_DEBUG_NAME)。您必须传递一个指向LUID类型变数的指标给lpLuid参数,系统将会为要求的权限填入LUID。

现在我们需要探索权限如何从安全性资料库取得我们的权杖。您必须了解权杖中找到的权限,是授予使用者帐户的权限和授予使用者为成员之每个群组权限的混合。

一旦系统建立权杖后,权杖中的权限就被会固定-意即它们不能被增加或移除。假如我们可以增加一个权限到权杖中,Windows 2000的安全性将被大大地破坏。然而,权限维持一个指出它们是否为启用或停用的状态。

当系统呼叫PrivilegeCheck时,假如被要求的权限是无效的,这个函数将会执行失败。为了使问题复杂化,有些系统在试图呼叫PrivilegeCheck前,会自动地呼叫您权杖的启用权限。在这些实例中,保持权限就可以使函数执行成功。

为了要了解哪个函数要求一个启用的权限,您必须阅读文件并偶尔从事一些试验及尝试错误行为。

在呼叫安全函数之前,您必需调整权杖的权限,让它成为启用或停用必要的权限。这可经由呼叫AdjustTokenPrivileges完成:

BOOL AdjustTokenPrivileges( 

HANDLE hTokenHandle,
BOOL fDisableAllPrivileges,
PTOKEN_PRIVILEGES pNewState,
DWORD dwBufferLength,
PTOKEN_PRIVILEGES pPreviousState,
PDWORD pdwReturnLength);

第一个参数为hTokenHandle,指出您想要修改权限状态的权杖。fDisableAllPrivileges参数为TRUE时,会导致所有在权杖中的权限都被停用,不理会传递进pNewState参数的任何东西。在这种情形下,您应该传递NULL给pNewState。当您只启用或停用授予权杖的子权限时,您通常会使用pNewState参数。pNewState参数是一个指向TOKEN_PRIVILEGES结构的指标,以下是它的函数定义:

typedef struct _TOKEN_PRIVILEGES { 

DWORD PrivilegeCount;
LUID_AND_ATTRIBUTES Privileges [ANYSIZE_ARRAY ];
}TOKEN_PRIVILEGES;

请注意,权限是一个LUID_AND_ATTRIBUTES结构的可变大小阵列。您想要在权杖中调整的每个权限结构皆应该在阵列中,而且PrivilegeCount 成员应该反映出权限的数量。以下是LUID_AND_ATTRIBUTES结构的定义:

typedef struct _LUID_AND_ATTRIBUTES { 

LUID Luid;
DWORD Attributes;
}LUID_AND_ATTRIBUTES;

阵列中每个结构的Luid成员应该被设定为考虑之权限LUID。最后, 属性 成员应该被设定为0,用来停用权限,或被设定为SE_PRIVILEGE_ENABLED,用来启用权限。

AdjustTokenPrivileges函数的dwBufferLength参数指出经由pPreviousState指向缓冲器以位元组计算的长度,它会指向一个接收权限之先前状态的缓冲器。假如不需要先前的状态资讯,可以传递NULL给pPreviousState。如果需要先前的状态资讯,就必须提供一个充分大小的缓冲器。一个指向需要大小的指标会被传回到pdwReturnLength参数中。经由pPreviousState指向的缓冲器与TOKEN_PRIVILEGES结构与您为pNewState参数建立的嵌入阵列一样被建立。

如您所见,启用及停用个别权限是很重要的工作。然而,您将发现它也是很常见的工作。我常认为Windows的开发人员应该提供一个shorthand函数,就像以下的EnablePrivilege函数,定义了某些重要的事,并提供容易的权杖权限存取。

BOOL EnablePrivilege( 

HANDLE hToken,
PTSTR szPriv,
BOOL fEnabled);

szPriv参数是个字串,表示启用及停用权限的程序名称,fEnabled参数简单地指出是否启用及停用权限。TokenMaster范例应用程序中实作了这样的函数,如下所示。

BOOL EnablePrivilege(HANDLE hToken,LPTSTR szPriv,BOOL bEnabled) 

{
TOKEN_PRIVILEGES tp;
LUID luid;
BOOL bRet =FALSE ;
__try{
//首先查询系统唯一的权限LUID
if(!LookupPrivilegeValue(NULL,szPriv /*SE_DEBUG_NAME*/,&luid))
{
//假如名称是膺造的...
__leave ;
}
//建立我们的权杖权限「阵列」(我们的实例是一个阵列)
tp.PrivilegeCount =1;
tp.Privileges [0 ].Luid =luid;
tp.Privileges [0 ].Attributes =bEnabled?SE_PRIVILEGE_ENABLED:0;
//经由启用及停用这一个权限,调整我们的权杖权限
if(!AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
NULL,
NULL ))
{
__leave ;
}
bRet =TRUE ;
}__finally{}
return(bRet);
}

说明

系统已经实作了另一个名称为AdjustTokenGroups的函数,除了可让权杖群组的启用及停用取代权限外,它的呼叫惯例与AdjustTokenPrivileges非常类似。然而,权杖群组的启用及停用并不常用。TokenMaster范例应用程序展示了一个AdjustTokenGroups的例子。

 

评分:0

我来说两句

seccode