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

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

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


设定预设的DACL
 

较少见的设定权杖预设DACL工作,比调整权杖的权限简单。权杖的预设DACL定义了以预设安全性建立安全物件的安全性存取。安全物件包括建构如文件、Mutexes(互斥)及线程的部份。安全物件通常会经由传递NULL以作为建立函数的LPSECURITY_ATTRIBUTES参数,并以预设安全性建立(有关这个主题的更多资讯,请参阅 第十章 的内容)。藉由移除应用于程序代码之安全性所建立的每个物件之必要性来修改预设的DACL,可以大大地简化伺服端的程序代码。

经由使用SetTokenInformation函数,您可以设定权杖的预设DACL和它的预设拥有者,以及主要的群组(它们都不应该混淆权杖使用者的身分识别,并且不能被改变):

BOOL SetTokenInformation( 

HANDLE hTokenHandle,
TOKEN_INFORMATION_CLASS TokenInformationClass,
PVOID pTokenInformation,
DWORD dwTokenInformationLength);

hTokenHandle参数是您要修改的权杖handle。TokenInformatonClass被用来指出您想改变的权杖部分。 前面已经讨论过您可选择的部分,在〈读取权杖资讯〉一节中所列的项目符号清单中。

SetTokenInformation的dwTokenInformationLength参数指出由pTokenInformation指向的缓冲器长度。有关作用中的SetTokenInformation完整范例,请参阅 TokenMaster范例应用程序 的内容。

使用权杖执行程序代码
 

到目前为止,我们已经讨论过从权杖中可以找到什么以及您可以对权杖做调整的内容。然而直到您开始在除了自己的处理程序权杖之外的权杖下执行程序代码,权杖才会开始产生作用。

以下有两种方法:

  • 用新的权杖建立一个新的程序。
     
  • 用您程序中的线程模拟一个权杖。
     

首先我们讨论如何在与您不同的使用者环境下建立一个新的程序,因为它是除了您以外的使用者执行程序代码时所用方法中较不复杂的一种。最后我们将会讨论到模拟的部份。

使用权杖建立一个程序时,应该呼叫CreateProcessAsUser:

BOOL CreateProcessAsUser( 

HANDLE hToken,
PCTSTR pszApplicationName,
PTSTR pszCommandLine,
PSECURITY_ATTRIBUTES psaProcessAttributes,
PSECURIT, Y_ATTRIBUTES psaThreadAttributes,
BOOL fInheritHandles,
DWORD dwCreationFlags,
PVOID pEnvironment,
PCTSTR pszCurrentDirectory,
PSTARTUPINFO pStartupInfo,
PPROCESS_INFORMATION pProcessInformation);

除了第一个hToken参数外, CreateProcessAsUser与CreateProcess的参数完全相同,它接收使用者环境的主要权杖,新的处理程序将在这个使用者环境下执行(有关CreateProcess的广泛讨论,请参考《Programming Applications for Microsoft Windows, Fourth Edition》一书的内容)。

现在让我们看看它们的差别。假如新的处理程序被建立,则Create ProcessAsUser会传回TRUE,反之,函数执行失败则传回FALSE。在叁种常见的情形下,CreateProcessAsUser可能会执行失败,而CreateProcess则不会。

在第一个案例中,呼叫处理程序可能没有可执行的文件或可执行之文件目录的存取权。在本机帐户中执行的服务不太可能会碰到这个问题,虽然它的确有可能发生。为了避开这个问题,您必须暂时模拟经由传递到CreateProcessAsUser的相同权杖建立新处理程序的使用者。这种暂时的模拟必需在呼叫CreateProcessAsUser前完成。当然,如果新的使用者没有可执行档或目录的存取权,则函数执行失败。

在第二个案例中,CreateProcessAsUser要求呼叫的程序拥有被授予权杖的SE_ASSIGNPRIMARYTOKEN_NAME及SE_INCREASE_QUOTA_NAME权限。这个规则的例外是案例中传递给CreateProcessAsUser的权杖,它是一个用呼叫程序权杖建立的受限权杖。在这种情况下,不需要SE_ASSIGNPRIMARYTOKEN_NAME权限(使用受限权杖是个非常强大的技巧,本章稍后会讨论一些细节)。这个情形的理由是受限权杖拥有比当前程序还少的系统存取权。

在第二个案例中,当传递给hToken参数的权杖不是一个主要的权杖时,CreateProcessAsUser会执行失败。假如您持有一个模拟权杖的handle,则您可以呼叫DuplicateTokenEx将它转变成主要的权杖:

BOOL DuplicateTokenEx( 

HANDLE hExistingToken,
DWORD dwDesiredAccess,
PSECURITY_ATTRIBUTES pTokenAttributes,
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
TOKEN_TYPE TokenType,
PHANDLE phNewToken);

hExistingToken参数是您要复制的权杖。这个权杖可以是主要权杖或是模拟权杖。就新的权杖而言,dwDesiredAccess参数指出您想要的存取权。您应该只要求完成手边工作所需要的权利即可。有关存取权利清单,请参阅 表格11-2 。

pTokenAttributes参数指出新权杖的安全描述项及其继承属性。不要把这个参数与权杖的预设DACL混淆了-此参数为新的物件设定存取控制(安全描述项及存取控制在 第十章 有详细地讨论)。

ImpersonationLevel参数指出新权杖的模拟等级,它可以是表格11-3中的任何值。

 表格11-3 SECURITY_IMPERSONATION_LEVEL列举类型的成员
叙述
SecurityAnonymous 用SecurityAnonymous模拟等级建立的权杖,不能用模拟建立一个处理程序。
SecurityIdentification 用此模拟等级建立的权杖,只能被用来作为身分识别的方法。权杖的使用者及群组可以被查询,但是权杖不能与模拟一起使用,或在呼叫CreateProcessAsUser函数中使用。
SecurityImpersonation 这个模拟等级建立一个具有完全功能的权杖,它不但可以被查询,而且可以用来透过模拟执行程序代码。权杖在线程可模拟之前,必须是个模拟权杖。
SecurityDelegation 有SecurityDelegation模拟等级的权杖,可以被用来存取网路来源。这被称为 委派 ,而且在连接次要的伺服端里,可让伺服端变成代表它客户的客户端。Windows NT 4.0及较早的版本不支援委派。Windows 2000也是,但是它需要委派在服务器试图建立一个委派类型的权杖时被允许。

TokenType可以是TokenPrimary或者TokenImpersonation,都是TOKEN_TYPE列举型别的成员。最后一个参数phNewToken,它会收到新权杖的handle。当您用完此物件时,请记得呼叫CloseHandle关闭它。

假如DuplicateTokenEx传回FALSE,则表示函数已经执行失败。它失败的原因通常会是原始权杖上的存取权不够(有关存取控制及存取权利的完整讨论,请参阅 第十章 )。


说明

Windows先前的版本中,为了代表客户端行为的目的而在伺服端机器上建立的权杖被称为网路权杖,它通常拥有SecurityImpersonation模拟等级。这些权杖不包含信任成员凭证的副本,并且不能被用来存取建立此权杖之机器外的资源。

然而,Windows 2000使用Kerberos安全性协定以支援SecurityDelegation模拟等级(在第十二章中讨论)。现在要拥有一个不限制存取本地端机器的网路权杖是可能的。


使用LogonUser取得权杖
 

现在您已经知道从程序中取得权杖,以及如何使用任一权杖建立处理程序的方法。然而我们尚未讨论当您只有使用者名称及密码,要如何撷取权杖handle的方法。您可以经由呼叫LogonUser来达成它:

BOOL LogonUser( 

PTSTR pszUsername,
PTSTR pszDomain,
PTSTR pszPassword,
DWORD dwLogonType,
DWORD dwLogonProvider,
PHANDLE phToken);

pszUsername及pszDomain参数指出您想要收到的使用者名称及网域的权杖。您可以传递句点字元(「.」)给pszDomain参数,使它只搜寻本机系统的帐户资料库。假如您传递NULL给pszDomain参数,则本机系统会在信任的网域中搜寻使用者。第叁个参数pszPassword,是这个帐户的密码。

LogonUser的dwLogonType参数,会向系统描述权杖如何被使用以及您想收到的权杖类型。表格11-4中列出您可以传递给dwLogonType参数的值。

 表格11-4 您可以传递给LogonUser的dwLogonType参数的值
叙述
LOGON32_LOGON_ INTERACTIVE 传递这个值给LogonUser,使系统检查要求权杖的使用者帐户中,是否有SE_INTERACTIVE_LOGON_NAME权限存在。假如使用者没有被指派这个权限,则LogonUser执行将会失败。此外,用这个登入收到的权杖会与系统一起快取。这意味着本机系统可能会与验证机器失去联络,但是将来使用快取凭证呼叫LogonUser时,仍旧会执行成功。LogonUser将传回一个主要的权杖。
LOGON32_LOGON_ BATCH 传递这个值给LogonUser,使系统检查要求权杖的使用者帐户中,是否存在SE_BATCH_LOGON_NAME权限。假如使用者没有这个权限,则LogonUser将执行失败。用这个登入类型而收到的权杖不会被快取,它会提高LogonUser的效能并使这个登入类型适合高效能的服务器。LogonUser会传回一个主要的权杖。
LOGON32_LOGON_NETWORK 传递这个值给LogonUser,使系统检查要求权杖的使用者帐户中,是否存在SE_NETWORK_LOGON_NAME权限。假如使用者没有这个权限,则LogonUser将失败。用这个登入类型而收到的权杖不会被快取。另外,这个权杖将会是个模拟权杖及「网路权杖」。
LOGON32_LOGON_ NETWORK_ CLEARTEXT 跟LOGON32_LOGON_NETWORK登入类型一样,这个登入类型会检查讨论中帐户的SE_NETWORK_LOGON_NAME帐户权利。然而,不像LOGON32_LOGON_NETWORK一般,当preserving信任成员凭证的副本使用产生的权杖存取网路时,这个登入类型会传回一个模拟权杖。该权杖必需在它可以被用来呼叫CreateProcessAsUser前,即被复制成主要的权杖 。
LOGON32_LOGON_ NEW_CREDENTIALS 这个是Windows2000的新结构登入类型。它要求您使用LOGON32_PROVIDER_WINNT50作为呼叫LogonUser中的dwLogonProvider值。这个登入类型会复制呼叫线程的程序权杖,并且将次要的身分识别加到权杖中。这个次要的身分识别将是所有网路存取权杖的身分识别,本地端机器的权杖身分识别仍然会跟原始权杖一样。这使得LOGON32_LOGON_NEW_凭证为唯一的,因为它使用现行的权杖,并用额外的凭证建立一个新的权杖。有关这个登录类型的范例,请看Windows 2000提供的RunAs.exe公用程序。
「/NetOnly」参数会使用LOGON32_LOGON_NEW_CREDENTIALS登入类型为新的程序建立一个权杖。这个被产生的权杖是一个主要权杖。
LOGON32_LOGON_SERVICE 传递这个值给LogonUser,使系统检查要求权杖的使用者帐户中,是否存在SE_SERVICE_LOGON_NAME权限。假如使用者没有被指派这个权限,LogonUser将执行失败。如果机器与验证代理程序失去联络时,为了将来还能呼叫LogonUser,这个权杖会被快取。LogonUser会传回一个主要权杖。
LOGON32_LOGON_ UNLOCK 这个登入类型被GINA用来处理未锁定的工作站。假如这个系统的稽核被启动时,可用这个登入类型呼叫LogonUser,以便在事件日志中建立一个项目。所产生的权杖是个主要权杖。

作为一个开发人员或网路管理员,您可以绑紧您的安全性,并且使系统更安全来预防建立了只能与LOGON32_LOGON_SERVICE或LOGON32_ LOGON_INTERACTIVE类型一起作用的使用者帐户的误用。例如,您只能分别授予SE_SERVICE_LOGON_NAME或SE_INTERACTIVE_LOGON_NAME权限。

 

评分:0

我来说两句

seccode