9. 信任成员的军事管制

http://blog.csdn.net/showna/article/details/1543523

 

Microsoft
的开发者现已就Microsoft Windows
2000安全性特色的计划性工作,这些安全性特色于大多数丁所习惯的条件还扑朔迷离且又有弹性。事实上,若加上适量的治本与软件开发,Windows
2000凡是本最先进且安全的操作环境之一。然而,由于这样复杂而起的汪洋细节以及错综复杂难了解的处,将使对Windows安全性没经历的多数开发者感
到气馁。就本书的读者与本人而言,这个安全性的主题虽然代表一个挑战,但应付挑战后报偿将是负有安全性的伺服端软件以及事实上的引以自豪。

于「安全性」这个主题下,Windows
2000起那么些得体的特征,大部份将当本书的即时等同篇谈论。本书以Windows安全性相关的风味分为同样要再多单如下所陈述之题目:

  •  身份鉴别与使用者内容 成百上千Windows安全性为使用者也根基,并且用她的力用在使用者识别以及保护「使用者内容」上。这个力量只是让系统控制使用者是否让允许实施某些动作。
     
  •  存取控制 存取控制与私资料以及文书以及注册密钥等系统物件的安全性有关。Windows
    2000之存取控制特色应用以身份辨别以及使用者内容达到,其负的程度在后头的少数独章中起谈论时会见还了解。
     
  •  安全性连线 简报安全性是Windows
    2000底一个着重部份,包括资料加密和验证,两者均确保您着跟一个可信赖的实体通讯。
     

因为安全性非常靠让使用者身份识别的建及保管,所以我们设开谈论Windows
2000之信任成员的动。

叫信任成员?
 

当你登入一尊执行Windows的机,通常会输入使用者名称与密码。使用者名称会向系统确认之代表你的帐号。像这样的帐号通常被称呼 使用者帐户 

一旦
用者帐户维持一组与使用者相关的资讯,例如,名字、密码(或身分证件)、注释及地点。有星星点点独必要项目及使用者帐户一起囤,即凡是使用者在系统及之权清单
以及数位身份鉴别-被称安全识别项或SID(读吧「sid」)-当在保护物件和私人资料的安时,系统会下它来确认帐户。SID是故来确认信任成
员帐户的可变长度二进制结构(权限和SID在稍后用生出详尽的座谈)。第叁独及使用者帐户同样重要之新闻是使用者成员的群组清单。

Windows开发人员实作了群组帐户,以管理复杂性的东西。 群组帐户 含有一组好是使用者帐户或是通用群组帐户的积极分子。群组帐户维持正跟使用者帐户相似之讯息,例如系统权限和SID。只要过将使用者帐户指派到群组帐户,可每当一个地方管理均等组使用者安全性而不要为每个使用者作调整。

使用者帐户及群组帐户是一个系统的信赖成员。 信任成员 大凡
在Windows中好拒绝或允许存取的实业。有些相信成员隐含在系面临(例如Everyone之内建群组),另一部分则由于网动态地成立(例如在第十与十
一律章会重新详细座谈的登入SID),还生任何以既起帐户而有的信任成员。使用者、群组及电脑都是与信赖成员帐户有关的Windows信任成员。所有的
信任成员分享遍及系统的公家函数,尤其是于拍卖存取控制时(在产同样段讨论)。


说明

使用者帐户及群组帐户是名为 信任成员 的普遍类别成员。因为就同一章节重点是座谈使用者及群组帐户,所以只有详细指明,否则 信任成员  信任成员帐户 这点儿独术语即表示使用者及群组帐户。



统经由信任成员帐户授予某个文件之存取或拥有权。当系统执行有特许的权力函数时,因为信任成员帐户已给予这个权力,所以其是深受允许的。当使用者被系统识
别时,是让她(他)的信任成员帐户及群组的相信成员帐户识别,而且使用者是这些帐户的成员。如你所见,信任成员是Windows安全性的要害部分。

以我们进来计划性的管制使用者及群组帐户的讨论之前,让咱们事先押一下管理体系信任成员的使用者介面。

Windows
2000底安全性工具
 

为实用地修具有安全性的软件,了解Windows
2000挨哪管理安全性与熟悉一些发生帮助的家伙是必不可少之。

第一,您而发生Windows
2000网的管理权限(或者,就网域系统而言是帐户操作者的权杖)。如果必要的话,安装一个因你也领导者的Windows
2000系统。


如还从未准备好的语句,现在呢应有对Microsoft Management
Console(MMC)较为熟悉了。这个应用程序会暨网共安装,而且属于MMC.exe。MMC可给您执行管理的职责,从装系统及的硬盘到监视事
件日志,包括安全性管理全是。实作MMC的每个函数如同给载入的嵌入式管理单元一般。有关以MMC的再次多细节,请参见Windows
2000 Help中之「使用Microsoft Management Console」主题。


机使用者及MMC的群组嵌入式管理单元不但可让你建立使用者及群组,也可以增加成员到群组中。嵌入式管理单元还得给你改变使用者的密码与规定部分适用于
信任成员的标准化。理想上,本书的范例应由管理群组成员的使用者执行(尽管你将发现建立权力较小之使用者及群组,才能够而你感受及权较小之方式重新易于学及
东西)。


组原则嵌入式管理单元可为你调整委派给信任成员的权限。因为系统及闹大气群组原则的意义,所以这个嵌入式管理单元比本机使用者及群组嵌入式管理单元更复
杂。经由展开以下的途径可以直接到群组原则嵌入式管理单元的权杖功能:本机电脑原则/电脑配置/Windows设定/安全性设定/本机原则/使用者权限委
派。图9-1说明了许展示的镜头。

 

 图9-1 显示在群组原则嵌入式管理单元中的权限画面

说明


过一个叫做群组原则的逻辑层来了解Windows
2000蒙有关权限的MMC嵌入式管理单元介面是根本之。群组原则是单复杂的主题,可以独立写成好几段。这个委派权限的主意是于Windows
NT直接委派权限给信任成员的使用者管理员工具中分离出去的道。透过呼叫系统函数,直接的权位操作还是是唯恐的;然而,Windows
2000供的使用者介面只有用到群组原则。
使用MMC嵌入式管理单元,您得体会委派使用者权限的经过。此外,委派使用者权限可能会见给网域群组原则完全地埋。您可采取直接管理权限的工具来处理
这些地下的问题。



后,在登计划性管理信任成员的座谈之前,我应当提到以本章稍晚所讲述的TrusteeMan范例应用程序,该范例程序能够于用来树立与删除使用者和群组帐
户,并委派权限给信任成员帐户的工具。尽管这个范例是只教学用的工具,但其吗对Windows
2000所涵盖的MMC嵌入式管理单元提供一个简的选。

管住信任成员帐户
 


典型的店铺环境里,系统管理者或者帐户操作者可以于网上起使用者及群组帐户。在这种条件下实施的服务器软件可以同已启用的安全性感知和使用者识别并
运作,不用直接建立或者管理信任成员帐户。这个软件就假定这些帐户已由外一个实体建立,这样的话,许多之劳务开发人员似乎都不用计划性地建立信任成员帐
户。


管这恐怕是真的,但是你会发现Windows
2000之安全性具有特别十分的弹性。您可以自动创造信任成员,不需与一定的使用者直接挂钩在协同,也毫无总是为早已登入系统的使用者用。举例来
说,Windows
2000而让您将使用者帐户的存取限制为和她的原来权限和由于软件决定的深信成员权相结合,它是平等栽 建立Restricted
Token 
的技艺(Restricted
Token于第十一段来详实的座谈)。如此一来,您的软件就足以成立系统管理者无法(或要求)手动建立的帐户。


外,假如你在编辑得直接支援建立帐户的服务器软件,例如Internet
gaming群体(Internet gaming community)或是前端(Front
End)连线银行,您的服务得能够统筹的成立和保管信任成员帐户。Windows
2000供零星组而给您这般做的函数:

  • Net API 「Net」函数可为您建立与管理任何Windows
    2000系及之使用者帐户,包括工作站和服务器系统,不管系统是否也网域控制站。
     
  • Active Directory Services
    Interface(ADSI) ADSI是如出一辙组COM物件,可给您于Windows
    2000上管理Active Directory。Active Directory是Windows
    2000网域上具备使用者及群组帐户(在广大另的物件中)的器皿,对Windows来说是个老关键的增大部分。您的软件可使ADSI物件来起、
    删除及管制网域控制站之Active Directory上的使用者及群组物件。
     

彻底
据您的急需来支配使用啊一样组APIs。Active
Directory是个店管理工具,就那个自我而言,假如你的软件正在铺条件遭到建立使用者帐户的话,应该使用Active
Directory的ADSI介面。然而,如果你的劳务软件在或者不是网域控制站的十足服务器遭受成立本机的相信成员帐户时,您见面发觉Net函数的应用变
得又简短且还直接。


说明

ADSI
物件可被您的软件管理不网域控制站系统及之使用者及群组,但是以这种系统未会见维护Active
Directory,所以ADSI物件可以仅经Net函数传递。同样地,假如Net函数给用来增加、移除或管理网域控制站直达之深信成员,他们以见面自动地
使用ADSI物件去窜机器上的Active Directory。


由于Net函数最经常给用,因此这同样节会集中吃斯有。然而,可给用来实行类似任务的ADSI元件也会盖注释的艺术列举出,以便你得于《Platform
SDK》文件被寻觅特定的主题。

认识Net函数
 

Net
API有诸多底特色都含多使管理信任成员帐户更为容易的函数和布局。Net函数而被你管理使用者帐户、本机群组帐户(只同纯机器相关联)及存在为网
域控制站和整网域函数的网域或通用群组帐户。这些函数以稳住都适合逻辑的办法设计,我们得过对有的规则的摸底而上学及大多。


说明


如您正编辑一个或者呼叫Net函数的故模组,您的旧模组及专案必须实施几个步骤。跟大部分Win
32受之API函数不同之是,Net函数不待以Windows.h的标头档中宣告。因此,您必须于模组的一模一样方始就带有符合Lm.h标头档。同样地,您必须用
NetApi32.lib文件加到与专案连结的程序库文件清单中。


Net函数的里一个特色是以同一的不二法门表现。因为是由,才会在不涵盖API命名集的每个单一函数的景下,提供了解这些函数的通用规则之内容:

  • Net函数使用Net+[相信成员类型]+[实践的动作]格式为稳定的命名。例如:NetUserAdd、NetLocalGroupGetInfo以及NetUserSetGroups。
     
  • Net函数单支援Unicode字串。假如你的专案以ANSI建立以来,在传递字串到Net函数前务必也每个字串缓冲器制作Unicode副本。(当以编排Windows
    2000底服务器软件时,这是其它一个时常应用Unicode的故。)
     
  • Net函数经由系统和帐户名称来分辨信任成员帐户。假设你在远端机器及有着足够的权柄,便可于远端系统上运这些函数管理信任成员。
     
  • Net函数实作了扳平组可用来向软件回报信任成员资讯或是被软件用来设定信任成员资讯的布局。因为牵涉到众多构造的部份,所以是Net函数的特点可能会见使人备感困惑,不过询问后会见坏合情且产生因此。
     

即时
里有只例:假如你运NetLocalGroupAdd函数(稍后拿详细地讨论)来建本机群组,您得选取输入及传递一个
LOCALGROUP_INFO_0组织的实例,只含群组名称,或是可叫你指定群组名称与注解字串的LOCALGROUP_INFO_1结构。这取决
您,而经由一个称level参数的传递,Net函数而叫你选择要动用的构造。在咱们的事例中,LOCALGROUP_INFO_0为level
0结构,而LOCALGROUP_INFO_1则是level 1结构。


说明


为一个纯的函数可以抱要回传一个之上之体系定义结构类型,Net函数定义之种类为PBYTE,并依据你所传递的讯息而相当的转型。假如你传递一个结构
给函数,则您应该传递者特定组织的指标,并将它们转型为PBYTE。如果Net函数回传一个构造为你,此时函数将会晤预期也一个PBYTE的指标,您得于微
后用她转型为适当的布局类型。


自己
在及时等同段谈论到的组织集将因为星号(*)代替level标记,以便归纳资讯而未用详实说明每个可用的结构。举例来说,在达标同样段落所涉嫌的有数个组织都以
LOCALGROUP_INFO_*
结构集中。我拿会晤讲有常以的结构和带有较少结构成员的有的特别布局。所有结构的事无巨细说明皆可在《Platform
SDK》文件中找到。

表9-1排有也信任成员管理所定义的构造集和可同步以的函数。

 表9-1 管理信任成员的结构集
结构集 用法及函数
GROUP_INFO_* 这些结构为通用或网域群组取得资讯以及设定通用群组资讯,在建立群组及对现存的群组操作时会使用到。

 函数: 

NetGroupAdd、NetGroupEnum、NetGroupGetInfo、NetGroupSetInfo

GROUP_USERS_INFO_* 在管理通用或网域群组中的使用者成员时会使用到这些结构,可用来为群组设定或取得使用者资讯。

 函数: 

NetGroupGetUsers、NetGroupSetUsers、NetUserGetGroups、NetUserSetGroups

LOCALGROUP_INFO_* 用来为本机群组取得以及设定资讯,不但会被现存的群组使用,在建立新的本机群组时也会用到。

 函数: 

NetLocalGroupAdd、NetLocalGroupEnum、NetLocalGroupGetInfo、NetLocalGroupSetInfo

LOCALGROUP_MEMBERS_INFO_* 用来为本机群组设定及取得成员清单。

 函数: 

NetLocalGroupAddMembers、NetLocalGroupDelMembers、NetLocalGroupGetMembers、NetLocalGroupSetMembers

LOCALGROUP_USERS_INFO_* 此组结构只包含一个称为LOCALGROUP_ USERS_INFO_0的结构,呼叫NetUserGet-Local Groups以取得本机群组成员之所有使用者帐户清单时使用。

 函数: 

NetUserGetLocalGroups

USER_INFO_* 由于Windows 2000使用者帐户联系的大量资讯,此组结构显然包含了最大的结构数量。建立使用者以及为现存使用者帐户取得和设定资讯时会使用到这些结构。

函数:

NetUserAdd、NetUserEnum、NetUserSetInfo、NetUserGetInfo

当Net函数将有关信任成员的情报回传到软件时,它以遣一个缓冲器给你。如前所述,Net函数得你传递指标位址到转型成PBYTE*
的适宜结构类型中。当你用了系统传回之缓冲器后,应该以她传递至NetApiBufferFree,以释放缓冲器。这个函数定义如下:

NET_API_STATUS NetApiBufferFree(PVOID pvBuffer);


设定信任成员资讯时,Net函数可能会见咬定软件并从未正确地设定结构成员。在这情形下,「Set」函数(如NetUserSetInfo)会回传
ERROR_INVALID_PARAMETER。为了确定错误的因,您可以运用函数的一无是处参数,这个参数会让填入一个先行定义之价,以指出首先单导致
错误的构造成员。假如你对之消息不感兴趣,可以传递NULL给「Set」函数。

有了Net函数的常识,您将发现上这些细节是起易的转业。所以,让我们开始成立信任成员帐户吧!

建立信任成员帐户
 


使用者及群组帐户在系被决定存取安全物件的角色,以及系统权限的功力来说是看似之。系统可被你交替地叫以及否决使用者和群组帐户的权。然而,使用者
可以使使用者帐户登入系统,反之,群组帐户却无力回天以这种方法采取。这种与使用者结合的图景,使得系统必须为使用者帐户维护大量的资讯。


说明


域或通用群组帐户在多观念与软件达到均同本机群组帐户一样。尽管自打此处开以讨论本机群组的治本细节,但是于统筹地保管通用群组时,许多观念要适用
的。有关Net API通用群组功能的一体化讨论,请参见《Platform
SDK》文件中配首为「NetGroup」的函数组。


汝可以下NetLocalGroupAdd函数来起本机群组帐户,其原型如下:

NET_API_STATUS NetLocalGroupAdd(
    PCWSTR  pstrServername,
    DWORD   dwLevel,
    PBYTE   pbBuf,
    PDWORD  pdwParmErr);

第一独参数是公想建之群组帐户的系统名称。传递NULL给pstrServername表示若要当本机系统上树一个群组。dwLevel参数指出您将传递让pbBuf参数作为参考的构造类型。NetLocalGroupAdd使用 

typedef struct _LOCALGROUP_INFO_0 {
    PWSTR lgrpi0_name;
}LOCALGROUP_INFO_0;

typedef struct _LOCALGROUP_INFO_1 { 
PWSTR lgrpi0_name; 
PWSTR lgrpi0_comment;
}LOCALGROUP_INFO_1;

上述两单结构还蕴涵一个群组名称字串的指标,LOCALGROUP_INFO_1布局尚带有一个注解字串的叠加指标。当您当确立群组时,这有限个组织都得以以。


后一个传递给NetLocalGroupAdd的参数是pdwParmErr,是单DWORD的指标。对于非恰当的参数,系统传回一个指出在
pdwParmErr参考的变数中,不适宜的参数值。只有NetLocalGroupAdd的传回值等于ERROR_INVALID_PARAMETER
时,传回pdwParmErr的价值才有效。表9-2排有这些恐怕的值。假如你不思量要收取这些新闻,可以传递NULL给pdwParmErr。

 表9-2 pdwParamErr参数中可能被传回的值
叙述
LOCALGROUP_NAME_PARMNUM 这个值表示您指定了一个无效的群组名称给新的群组。
LOCALGROUP_COMMENT_PARMNUM 这个值表示呼叫NetLocalGroupAdd中的注解值是无效的。

你该经常检查NetLocalGroupAdd的传回值以保险系统已经扩散NERR_Success。否则表示系统以起的初本机群组时实施破产。


说明

ADSI
套件也足以为此来确立群组帐户。Active
Directory被组织成为层级物件,可以在另的容器物件中确立群组物件。您得用IADsContainer介面的Create方法成立一个群组物
件。一旦确立物件后,您得下QueryInterface方法获得IADsGroup介面的指标,它可以用来再进一步地管理新的群组物件。要得到更多
的细节,请参见《Platform SDK》文件。


确立使用者帐户与建立群组帐户的办法类似;然而,您可以提供再多使用者帐户的消息给系统。您可以使用NetUserAdd函数在Windows
2000系及成立新的使用者。

NET_API_STATUS NetUserAdd(
    PCWSTR pstrServername,
    DWORD dwLevel,
    PBYTE pbBuf,
    PDWORD pdwParmErr);


注意到NetUserAdd与NetLocalGroupAdd的参数清单完全相同,差别在传递到pbBuf参数的布局类型。您可传递指标到
level 1、2或者3的USER_INFO_*
结构,以起新的使用者。这里是USER_INFO_1(可以同NetUserAdd一起行使的极其简单易行结构)及USER_INFO_3(您得行使的卓绝广
泛结构)的定义。

typedef struct _USER_INFO_1 {
    PWSTR usri1_name;
    PWSTR usri1_password;
    DWORD usri1_password_age;
    DWORD usri1_priv;
    PWSTR usri1_home_dir;
    PWSTR usri1_comment;
    DWORD usri1_flags;
    PWSTR usri1_script_path;
}USER_INFO_1 ;
typedef struct _USER_INFO_3 {
    PWSTR usri3_name;
    PWSTR usri3_password;
    DWORD usri3_password_age;
    DWORD usri3_priv;
    PWSTR usri3_home_dir;
    PWSTR usri3_comment;
    DWORD usri3_flags;
    PWSTR usri3_script_path;
    DWORD usri3_auth_flags;
    PWSTR usri3_full_name;
    PWSTR usri3_usr_comment;
    PWSTR usri3_parms;
    PWSTR usri3_workstations;
    DWORD usri3_last_logon;
    DWORD usri3_last_logoff;
    DWORD usri3_acct_expires;
    DWORD usri3_max_storage;
    DWORD usri3_units_per_week;
    PBYTE usri3_logon_hours;
    DWORD usri3_bad_pw_count;
    DWORD usri3_num_logons;
    PWSTR usri3_logon_server;
    DWORD usri3_country_code;
    DWORD usri3_code_page;
    DWORD usri3_user_id;
    DWORD usri3_primary_group_id;
    PWSTR usri3_profile;
    PWSTR usri3_home_dir_drive;
    DWORD usri3_password_expired;
}USER_INFO_3 ;


您所显现,当您在起使用者时,可以择传递大量底资讯给系统。有关USER_INFO_2及USER_INFO_3组织面临每个成员的事无巨细描述,请参见
《Platform
SDK》文件。此处的座谈才待叙述在USER_INFO_1布局中起的积极分子,这些成员会在表9-3负列有。

 表9-3 USER_INFO_1的成员
成员 叙述 如果ERROR_INVALID_ PARAMETER,pdwParmErr 的传回值
usri1_name 指向一个包含建立使用者帐户的Unicode使用者名称缓冲器。此成员必须包含一个有效的指标,否则NetUserAdd将传回ERROR_INVALID_PARAMETER。 USER_NAME_PARMNUM
usri1_password 指向一个包含建立使用者帐户的Unicode密码缓冲器。密码限制为14个字元而且必须符合您正在新增使用者帐户之系统提出的规则。 USER_PASSWORD_PARMNUM
usri1_password_age NetUserAdd忽略此成员。 USER_PASSWORD_AGE_PARMNUM
usri1_priv 当您在建立使用者时,这个成员的值必须设定为USER_PRIV_USER。任何其他的值将会导致NetUserAdd传回ERROR_INVALID_PARAMETER。 USER_PRIV_PARMNUM
usri1_home_dir 使用者可以为其帐户定义主目录。假如您想要联合主目录与新的使用者,此成员应该要指向一个包含Unicode字串目录路径的缓冲器。您可以指派NULL给这个成员。 USER_HOME_DIR_PARMNUM
usri1_comment 这个成员指向一个包含新使用者的Unicode注解缓冲器。假如您不想要结合注解与新的使用者帐户,可以指派NULL给这个成员。 USER_COMMENT_PARMNUM
usri1_flags 这个成员可以结合指示新使用者帐户功能的标记(请见 表9-4 )。 USER_FLAGS_PARMNUM
usri1_script_path 当使用者登入系统时,系统将执行与您的使用者结合之 .exe、.cmd或.bat档。您可以使用此成员来设定登入指令档的路径。 USER_SCRIPT_PATH_PARMNUM

呼唤NetUserAdd时,表9-4蒙其他一样种植标志的组合还足以被派出给USER_INFO_1的usri1_flags成员,其他的符号则可用来指定额外的风味。有关这些其他标志的消息,请参见《Platform
SDK》文件。

 表9-4 与USER_INFO_1有关的标记
标记 叙述
UF_ACCOUNTDISABLE 建立一个无效的帐户。
UF_PASSWD_NOTREQD 建立一个不需要密码的帐户。对于要求所有帐户都需使用密码的系统或网域来说,可能是个适当的原则。
UF_PASSWD_CANT_CHANGE 建立一个使用者无法改变自己密码的帐户。系统管理者仍旧可以改变密码。
UF_DONT_EXPIRE_PASSWD 这个使用者的密码永不过期。
UF_NOT_DELEGATED 这个帐户不能被委派(有关委派的讨论,请参阅 第十一章 及 十二章 )。
UF_SMARTCARD_REQUIRED 要求使用者使用智慧卡登入这个新帐户。
UF_TRUSTED_FOR_DELEGATION 这个帐户可被委派(有关委派的讨论,请参阅 第十一章 及 十二章 )。

无其看起像什么,用NetUserAdd来树立新使用者帐户之低编写程序必要条件实际上是杀合情之。以下的程序代码说明了最为简便的实例:

BOOL CreateUser(PWSTR pszSystem, PWSTR pszName, PWSTR pszPassword){ 
    USER_INFO_1 userInfo ={0 };
    userInfo.usri1_name = pszName;
    userInfo.usri1_password = pszPassword;
    userInfo.usri1_priv = USER_PRIV_USER;

    NET_API_STATUS netStatus =
        NetUserAdd(pszSystem, 1, (PBYTE) &userInfo, NULL);
    return(netStatus == NERR_Success);
}

假若你所展现,这是只相当琐碎的程序代码,用来以给定的系统上和给定的称呼与密码建立平等位使用者。使用以下的道呼叫此范例函数将见面于本机系统及成立一个名字啊「MrMan」,密码为「HowDoYouDo」的使用者:

CreateUser(NULL, L"MrMan", L"HowDoYouDo");

说明

ADSI
套件也只是给用来树立使用者帐户。如同群组物件一般,可以以另外的容器物件中树立使用者物件。您可行使IADsContainer介面的Create成员
建立一个使用者物件。一旦确立了这物件,便足以使QueryInterface方法,以获IADsUser介面的指标,它而为用来更地保管而的
新使用者物件。有关这主题的细节,请参考《Platform SDK》文件。


设定使用者及群组资讯
 

连带
统也为拿走跟设定都于立之使用者或者群组帐户的消息而提供Net函数。您可望这些函数的呼叫格式与NetGroupAdd及NetUserAdd非
常类似。要获取跟设定使用者帐户资讯,可以采用NetUserGetInfo及NetUserSetInfo函数,其原型如下:

NET_API_STATUS NetUserGetInfo(
    PCWSTR pszServerName,
    PCWSTR pzUsername,
    DWORD dwLevel,
    PBYTE *ppbBuf);

NET_API_STATUS NetUserSetInfo(
    PCWSTR pszServerName,
    PCWSTR pszUsername,
    DWORD dwLevel,
    PBYTE pbBuf,
    PDWORD pdwParmErr);

一旦你所见,NetUserGetInfo及NetUserSetInfo函数拥有几跟NetUserAdd一样的参数清单。事实上,唯一额外的参数是pstrUsername,它指出为获取或者设定资讯的使用者名称。

告小心NetUserGetInfo的部份,其pbBuf参数已经深受转移化缓冲器的指标位址。如同先前所指出的,这是以系统实际上会指派被求的组织于你,并经ppbBuf参数在变数中传唱一个针对新缓冲器的指标。

dwLevel
参数指出在呼唤NetUserGetInfo或NetUserSetInfo中,将会晤使用到的USER_INFO_*
结构level。这些函数接受USER_INFO_1或USER_INFO_3,如同前面所定义的,以及NetUserAdd不支援的另外几只
USER_INFO_* 结构。有关这些组织的整体叙述,请参考《Platform
SDK》文件。


说明

设定使用者资讯时,您该利用一个独含有您想设定的资讯或收受NULL,如同一个成员值的结构level。举例来说,仅设定使用者帐户的密码可下USER_INFO_1003结构类型,因为它只有吧使用者的新密码包含一个分子。


因为
下的片独范例函数,说明了安以NetUserSetInfo及NetUserGetInfo来设定及沾使用者帐户资讯的计。第一独函数显示怎么也
使用者帐户设定密码;第二单函数则证实如何撷取使用者的注解栏位。这些函数使用的口径得以呢使用者帐户取得要设定任何有效的讯息。

BOOL SetUserPassword(PWSTR pszSystem, PWSTR pszName, PWSTR pszPassword){ 
    USER_INFO_1003 userInfo = {0};
    userInfo.usri1003_password = pszPassword;
    NET_API_STATUS netStatus =
        NetUserSetInfo(pszSystem, pszName, 1003, (PBYTE) &userInfo, NULL);
    return (netStatus == NERR_Success);
}

BOOL GetUserComment(PWSTR pszSystem, PWSTR pszName, PWSTR pszComment,
    int nBufLen){
    USER_INFO_10 *puserInfo;
    BOOL fSuccess = FALSE;
    NET_API_STATUS netStatus =
        NetUserGetInfo(pszSystem, pszName, 10, (PBYTE*) &puserInfo);
    if (netStatus == NERR_Success){
        if (nBufLen > lstrlen(puserInfo->usri10_comment)) {
            lstrcpy(pszComment, puserInfo->usri10_comment);
            fSuccess = TRUE;
        }
        NetApiBufferFree(puserInfo);
    }
    return(fSuccess);
}

说明

有着成功呼叫的NetUserGetInfo必须呼叫NetApiBufferFree,以自由NetUserGetInfo传回的缓冲器。NetApiBufferFree函数被定义也博得一个参数,它是为放走的缓冲器指标。


君或许曾经猜到,系统啊供了近似的函数,用来得到与设定群组信任成员帐户的情报。要博取信任成员资讯,您得呼叫NetLocalGroupGetInfo;而设定群组资讯则要呼叫NetLocalGroupSetInfo。这些函数定义如下:

NET_API_STATUS NetLocalGroupGetInfo(
    PCWSTR pservername,
    PCWSTR groupname,
    DWORD dwLevel,
    PBYTE *ppbBuf);

NET_API_STATUS NetLocalGroupSetInfo(
    PCWSTR servername,
    PCWSTR groupname,
    DWORD dwLevel,
    PBYTE pbBuf,
    PDWORD pdwParmErr);

只要您所呈现,呼叫这些函数和呼叫取得跟设定使用者帐户资讯的函数几乎完全相同,差别在你而拍卖的群组资讯及以前议论的LOCALGROUP_INFO_*
结构。

吁记得群组成员资讯也与群组帐户一起囤,尽管名称以及注解看起也许是跟群组帐户结合的最好少资讯。由于其跟SID主题精心相关,所以是主题将延到本章的末梢部分,在稍后之〈认识SIDs〉一省中拿讨论SIDs内容。

历数使用者及群组
 


常会于给定的系上取得现存使用者要群组的清单。再同差地证明,Net
API提供个别只类似的函数来实行这些任务。您可使用NetLocalGroupEnum去获取系统及之群组清单;同样地,也足以利用
NetUserEnum取得系统及使用者帐户的清单。这些函数定义如下:

NET_API_STATUS NetLocalGroupEnum(
    PCWSTR pszServerName,
    DWORD dwLevel,
    PBYTE* ppbBuf,
    DWORD dwPrefMaxLen,
    PDWORD pdwEntriesRead,
    PDWORD pdwTotalEntries,
    PDWORD_PTR pdwResumeHandle);

NET_API_STATUS NetUserEnum(
    PCWSTR pszServerName,
    DWORD dwLevel,
    DWORD dwFilter,
    PBYTE* ppbBuf,
    DWORD dwPrefMaxLen,
    PDWORD pdwEntriesRead,
    PDWORD pdwTotalEntries,
    PDWORD_PTR pdwResumeHandle);

当时
几函数很接近,但产生有差别值得注意。从LOCALGROUP_INFO_*
结构集中传回结构及NetLocalGroupEnum的以,将会晤于USER_INFO_*
结构集传回结构及NetUserEnum函数。此外,NetUserEnum可于你指定筛选标准,以调减使用者帐户清单传回的限制。传递0给
NetUserEnum的filter参数,表示从没筛选标准,所以任何的帐户类型且见面给传到。您便要传送FILTER_NORMAL_ACCOUNT
给filter参数;然而,您也足以传递表9-5遭到列有的其他一个价。

 表9-5 可以传递给NetUserEnum的filter参数的筛选条件值
意义
FILTER_NORMAL_ACCOUNT 传回系统上的通用使用者帐户资料
FILTER_TEMP_DUPLICATE_ACCOUNT 传回网域控制站上的本机使用者帐户资料
FILTER_INTER网域_TRUST_ACCOUNT 传回网域控制站上的网域信任帐户资料
FILTER_WORKSTATION_TRUST_ 传回网域控制站上的成员服务器或工作站帐 ACCOUNT 户资料
FILTER_SERVER_TRUST_ACCOUNT 传回网域控制站上的网域控制站帐户资料


了回传filter参数及组织外,NetUserEnum及NetLocalGroupEnum的应用是完全相同的。就如我们先看来底函数一
样,pszServerName参数指出我们怀念如果列举信任成员帐户的体系。dwLevel参数指出和ppbBuf参数相关的LOCALGROUP_
INFO_* 或USER_INFO_* 结构的版本。


应该传递要求作ppbBuf参数之结构类型指标变数的位址。根据NetUserEnum及NetLocalGroupEnum是否为下的图景,系统将
指派一个缓冲器以有USER_INFO_* 或LOCALGROUP_INFO_*
结构的阵列,ppbBuf是一个缓冲器位址的指标。这个缓冲器将是函数列举的帐户。记得就比如NetUserGetInfo一样,必须呼叫
NetApiBufferFree来刑释解教系统指派给你的缓冲器。


应该指示出呼叫函数所传回之缓冲器最充分容量,以各项元组来传递者尺寸为作为dwPrefMaxLen参数。假如你要是系尽可能指派更要命的缓冲器,可以传递
MAX_PREFERRED_LENGTH。这样的话,系统便会独家呼叫函数来就列举型别(Enumeration)的动作。

卿或许会见咨询为何连年挑三拣四范围「Net*Enum」传回的缓冲器大小,从而必须多次呼唤函数。这里产生几乎单由:不保险少数的帐户,而大气之帐户可能会见压倒系统指派的尽可怜缓冲器大小。此外,如果罗列型别是只长的先后,您可能会见想如果应用程序定期地取消对她的决定。


说明

因为您无法确定系会派多少的内存,所以无是否选择MAX_PREFERRED_LENGTH值为缓冲器的长度,您的程序代码都应当要会处理要求数呼唤列举函数的情状。


系统传回读取pdwEntriesRead参数所依赖的变数项目数量。其馀可用之类型(包括这些为染回的门类)总数会储存在pdwTotalEntries参数所指的变数中。

末段一个参数是系传回之值,在随着呼叫的罗列函数中得给传送回系统,用来持续接收帐户资讯。在您最初呼叫列举函数时,应该以pdwResume
Handle参数所依靠的变数设定也0,并且不应有改传回之价值。

如果都成地扩散资料,可是有重新多钱户为列举时,列举函数将污染回ERROR_MORE_DATA。当最后的可用帐户被盛传后,列举函数将回传NERR_
Success。

以下的程序代码说明了安使NetLocalGroupEnum列举本机系统及的群组,并展示在主控台视窗:

void PrintLocalGroups() {
    ULONG_PTR lResume = 0;
    ULONG lTotal = 0;
    ULONG lReturned = 0;
    ULONG lIndex = 0;
    NET_API_STATUS netStatus;
    LOCALGROUP_INFO_0* pinfoGroup;

    do {
        netStatus = NetLocalGroupEnum(NULL, 0, (PBYTE*) &pinfoGroup,
            MAX_PREFERRED_LENGTH, &lReturned, &lTotal, &lResume);
        if ((netStatus == ERROR_MORE_DATA) ||
            (netStatus == NERR_Success)) {
            for (lIndex = 0; lIndex < lReturned; lIndex++) {
                wprintf(L"%s/n", pinfoGroup[lIndex].lgrpi0_name);
            }
            NetApiBufferFree(pinfoGroup);
        }
    }while (netStatus == ERROR_MORE_DATA);
}

这个函数只待多少修改就得以NetUserEnum来列举系统及之使用者。

摧毁使用者及群组帐户
 

于切换工具与讨论识别信任成员帐户、SIDs的系统结构之前,我怀念只要讨论如何摧毁使用者及群组帐户的部份,以饱含使用者及群组管理之讨论。

当此时段摆到SID,是坐她确实跟信赖成员帐户的解构有些关系。尽管Net函数能叫你处理信任成员帐户的称谓,而其馀的体系大部分咸忽视和信赖成员帐户关联的号。取而代之的是系统会动及帐户关联的SID二上制值来鉴别某个帐户。这和摧毁信任成员帐户有啊关系吧?


如你使用名称也「JClark」建立一个亲信成员,然后还就此是帐户登入并确立一个文书,系统会主张自己是这个物件的主人。然而,如果你摧毁了自身之使用者
帐户,然后还为名称「JClark」重新建立一个新的使用者帐户,此时系统会指派不同之SID值,因此新的帐户无会见吃视为旧文件物件的主人。

那就是说,您得采取如下的函数来删除使用者帐户:

NET_API_STATUS NetUserDel(
    PCWSTR pszServerName,
    PCWSTR pszUsername);

而您所看到底,这个简单的函数只下系统名称及使用者帐户的称作为参数。PszServerName参数可以吧NULL,表示本机系统。假如是函数执行成功,将会传来NERR_Success。

Net
API为除去群组实作了一个好像之函数,其定义如下:

NET_API_STATUS NetLocalGroupDel(
    PCWSTR pszServerName,
    PCWSTR pszGroupname);

说明

公也可行使ADSI物件来列举及删除使用者及群组帐户,并得到跟设定使用者及群组资讯。有关IADsUser及IADsGroup介面和用来寻找和列举IdirectorySearch介面的座谈部份,请参见《Platform
SDK》文件。


管制群组成员
 


组成员资讯能盖几只点子修改,但是我们第一需要上学几个撷取群组成员资讯的艺术。第一只措施应用NetUserGetLocalGroups函数撷取为群
组成员的使用者清单;第二个方法应用NetLocalGroupGetMembers函数撷取与各自群组关联的成员组。

使用NetUserGetLocalGroups函数
 

NetUserGetLocalGroups函数的原型如下:

NET_API_STATUS NetUserGetLocalGroups(
    PCWSTR  pszServerName,
    PCWSTR  pszUsername,
    DWORD   dwLevel,
    DWORD   dwFlags,
    PBYTE*  ppbBuf,
    DWORD   dwPrefMaxLen,
    PDWORD  pdwEntriesRead,
    PDWORD  pdwTotalEntries);

倘若
您所呈现,这个函数和我们讨论了之NetLocalGroupEnum及NetUserEnum函数看起很类似。事实上,主要的不比处在于这个函数使用了
LOCALGROUP_USERS_INFO_*
结构集(LOCALGROUP_USERS_INFO_0至今准有)。

dwFlags
唯一有效之值即是LG_INCLUDE_INDIRECT,它指示NetUserGetLocalGroups也当传为间接成员群组的使用者(由
pszUsername指出),或者是0,即指示函数应该就招回为直接成员群组的使用者。当pszUsername为通用群组或是网域群组的成员时-即本
机群组的分子,可能吗会发生间接成员的状。

你得传递MAX_PREFERRED_LENGTH给dwPrefMaxLen参数,但是无论是采取何种措施,您还要注意过pdwEntriesRead参数与pdwTotalEntries参数传回的价,以确定有可能的色都被流传。

暨前面的罗列函数不同,它从不更呼叫NetUserGetLocalGroups继续列举的艺术。您不太可能会面临列举多于几十单群组的场面,而列举使用者或者会见传播数千独帐户项目。

使用NetLocalGroupGetMembers函数
 

老二单列举成员资讯的主意是撷取与个别群组关联的成员组。您应该采取NetLocalGroupGetMembers函数这样做:

NET_API_STATUS NetLocalGroupGetMembers(
    PCWSTR  pszServerName,
    PCWSTR  pszLocalGroupName,
    DWORD       dwLevel,
    PBYTE*  ppbBuf,
    DWORD       dwPrefMaxLen,
    PDWORD  pdwEntriesRead,
    PDWORD  pdwTotalEntries,
    PDWORD_PTR  pdwResumeHandle);

这个函数会取得服务器名称以及本机群组名称为作其的首先只参数。常见的dwLevel参数指出您想只要经ppbBuf参数传回的LOCALGROUP_MEMBERS_INFO_*
结构集level。

LOCALGROUP_MEMBERS_INFO_*
结构允许而处理信任成员称和网域名称,或是它们的SIDs,下一致节以作详细地说明。以下是LOCALGROUP_MEMBERS_
INFO_0 及 LOCALGROUP_MEMBERS_INFO_3 结构的概念:

typedef struct _LOCALGROUP_MEMBERS_INFO_0 {
    PSID   lgrmi0_sid;
}LOCALGROUP_MEMBERS_INFO_0;

typedef struct _LOCALGROUP_MEMBERS_INFO_3 {

    PWSTR   lgrmi3_domainandname;
}LOCALGROUP_MEMBERS_INFO_3;

说明

处理信任成员经常,了解很多安全性函数所要的SID值是蛮关键的。再者,就SIDs来说,本机群组成员的操作函数而被您撷取信任成员项目。


LOCALGROUP_MEMBERS_INFO_0中使用的PSID类型指出一个对准SID结构的指标。这些构造的别一个且可因你软件的消而同NetLocalGroupGetMembers一起利用。

dwPrefMaxLen、
pdwEntriesRead、pdwTotalEntries及pdwResumeHandle参数是惯用缓冲器大小、读取的色、剩下的种与连续
列举型别的值。这些参数和就讨论了之NetUserEnum及NetLocalGroupEnum函数中一律名称的参数一样,以完全相同的法运行。事
实上,为了和NetLocalGroupGetMembers一起用,NetLocalGroupEnum的同样部分范例函数
PrintLocalGroups,可以好地修改如下:

void PrintLocalGroupMembers(WCHAR *pszGroup) {
    ULONG_PTR lResume = 0;
    ULONG lTotal = 0;
    ULONG lReturned = 0;
    ULONG lIndex = 0;
    NET_API_STATUS netStatus;
    LOCALGROUP_MEMBERS_INFO_3* pinfoMembers;

    do {
        netStatus = NetLocalGroupGetMembers(NULL, pszGroup, 3,
            (PBYTE*) &pinfoMembers, MAX_PREFERRED_LENGTH,
            &lReturned, &lTotal, &lResume);
        if ((netStatus == ERROR_MORE_DATA) ||
            (netStatus == NERR_Success)) {
            for (lIndex = 0; lIndex < lReturned; lIndex++) {
                wprintf(L"%s/n",
                    pinfoMembers[lIndex].lgrmi3_domainandname);
            }
            NetApiBufferFree(pinfoMembers);
        }
    }while (netStatus == ERROR_MORE_DATA);
}

行使NetLocalGroupSetMembers函数来设定本机群组的积极分子:

NET_API_STATUS NetLocalGroupSetMembers(
    PCWSTR  pszServerName,
    PCWSTR  pszGroupName,
    DWORD       dwLevel,
    PBYTE       pbBuf,
    DWORD       dwTotalEntries);

PszServerName
及pszGroupName参数指示而着设定成员的系统名称和本机群组。DwLevel参数指出您想使采用的
LOCALGROUP_MEMBERS_INFO_*
结构集level。您得传递0或3,以个别代表LOCALGROUP_MEMBERS_INFO_0或
LOCALGROUP_MEMBERS_INFO_3,两者在稍微早且早已定义了。这象征你得选下信任成员帐户名称字串或是SIDs来设定成员。


应该传递一个指标到选的构造类型阵列给pbBuf参数,以及阵列中列之数码也dwTotalEntries参数的内容。假如函数执行成功,被
pbBuf以阵列传递的表示深信成员清单将凡以此群组的新成员清单。记住信任成员清单将会代替任一个现行的群组成员。如果函数执行成功,将污染回
NERR_Success。

别有效的函数
 

现行而明白撷取及设定有本机群组之信任成员的道,还有少只有效之函数,可给你于今天成员的群组中,只新增和删除特定的深信成员清单。这半独函数分别是NetLocalGroupAddMembers及NetLocalGroupDelMembers:

NET_API_STATUS NetLocalGroupAddMembers(
    PCWSTR  pszServerName,
    PCWSTR  pszGroupName,
    DWORD       dwLevel,
    PBYTE       pbBuf,
    DWORD       dwTotalEntries);

NET_API_STATUS NetLocalGroupDelMembers(
    PCWSTR  pszServerName,
    PCWSTR  pszGroupName,
    DWORD       dwLevel,
    PBYTE       pbBuf,
    DWORD       dwTotalEntries);

你可以使与NetLocalGroupSetMembers一样的主意利用这些函数。关于范例的部份,请参见本章稍晚叙述的 

认识SIDs
 

SIDs
对Windows
2000安全性来说是不可少的。SIDs在本章已具有提及,也延续的段也用再次出现,而今日幸详细认识SIDs的上。到目前为止,您了解SIDs
是安全识别项,它为网识别信任成员的质地。每个SID是一个象征相信成员的绝无仅有二前行制数值。

以下有几个您如果熟悉的泛工作:

  • 用一个使用者或者群组名称转换成SID。
     
  • 也信任成员以SID转换成为文字称。
     
  • 开始建立一个显的SID。这些SID存在有的系遭到,而且指出如Guest或Everybody帐户。
     
  • 复制SID结构。
     
  • 末段,来回地变换代表SID的二进制数值与字串。
     

SID是个安全识别项和朝网识别信任成员身分的组织。SID由48个各元值跟随一个32各第一的元件数字变数所做。在文件被,SID通常会因S-R-I-S-S…格式表示(请参见提要栏位)。


SID格式

SID的格式通常是:S-R-I-S-S…

在这里:

 S 使字面所勾画的「S」,指示这些序号是SID。

 R 凡SID的考订阶段,以一个数字代表(一般是1)。

 I 凡是独48I位元的数字,指示授权单位。

 S 大凡只32位第一数字,指示下的授权单位,亦即大家所了解之对立识别项或RID。

 S 举凡任何一个辅助授权单位。在SID中得以生出管一的次要授权单位数据。

 范例: S-1-5-11


自Windows
NT
3.1暨今天,SID结构的修订版本号码就是1;然而,结构是可能会见变动之,我们总有一天会视2之改动版本。授权单位「号码」指出SID在谁授权单位之下有-即什么「实体」拥有SID及管制它的帐户。表9-6提供现在发救助的授权单位清单。

 表9-6 SID授权单位
授权单位 定义
SECURITY_NULL_SID_ AUTHORITY 定义为0,这个授权单位被用来建立一个指出无效群组或没有人的SID。
SECURITY_WORLD_SID_ AUTHORITY 定义为1,这个授权单位被用来建立Everybody群组帐户。
SECURITY_LOCAL_SID_ AUTHORITY 定义为2,这个授权单位被用来建立众所周知的LOCAL群组帐户。
SECURITY_CREATOR_SID_ AUTHORITY 定义为3,这个授权单位与Creator Owner SID一起使用。
SECURITY_NON_UNIQUE_ AUTHORITY 定义为4,这个授权单位被用来产生不是唯一的SIDs。 第一个次要授权单位总是设为SECURITY_NT_NON_UNIQUE,定义为0x15。
SECURITY_NT_AUTHORITY 定义为5,这个授权单位由Windows 2000系统建立的使用者及群组帐户所使用。

附带授权单位凡唯一的32各类元值,与授权单位的SID相关。下一个次要授权单位凡唯一的,与原先之从授权单位与最后授权单位之SID相关。次要授权单位即便大家所知晓之RIDs。

表9-7显有明了的RIDs。(完整的清单请参考《Platform
SDK》文件中的WinNT.h。)和以前列出的授权单位不同的凡,这些RIDs并无全是唯一的,因为其是绝无仅有跟授权单位相关的,就那自身来说,不受授权单位的主宰是尚未意思之。

 表9-7 一些众所周知的RIDs
RID 有关的授权单位 定义
SECURITY_NULL_RID NULL 定义为0,这是NULL群组的个别次要授权单位。
SECURITY_WORLD_RID WORLD 定义为0,这是Everyone群组的个别次要授权单位。
SECURITY_CREATOR_ OWNER_RID CREATOR 定义为0,这是使用者Creator Owner的个别次要授权单位。
SECURITY_CREATOR_ GROUP_RID CREATOR 定义为1,这是使用者Creator Group的个别次要授权单位。
SECURITY_CREATOR_ OWNER_SERVER_RID CREATOR 定义为2,这是使用者Creator Owner Server的个别次要授权单位。
SECURITY_CREATOR_ GROUP_SERVER_RID CREATOR 定义为3,这是使用者Creator Group Server的个别次要授权单位。

经过把明显的RID与各自的授权单位结合,可以来大家所熟知的SID。众所周知的SIDs识别系统辨别使用者及被网定义且经过每个网路上设置Windows
2000之群组身分。表9-8列有有大家所熟知的SIDs及用法。

 表9-8 众所周知的SIDs及用法
SID 常见名称 用法
S-1-0-0 Null SID 指出一个空的或为NULL的群组。它被定义为唯一没有使用者的群组,通常用来指示没有人。
S-1-1-0 Everyone 指出一个所有信任成员皆为暗示性成员的群组。这是一个非常重要的SID,对于在系统中建立安全物件的存取清单是有帮助的。它也就是World SID或World群组。
S-1-2-0 Local SID 指出一个包括所有本地或实际登入系统的使用者群组。
S-1-3-0 Creator Owner SID 为某个物件的建立者充当替代符号(Placeholder)。它与可继承的存取控制清单一起使用。您将在第十章找到更多有关此SID的资讯。
S-1-3-1 Creator Group SID 为某个物件的主要群组建立者充当替代符号。它与可继承的存取控制清单一起使用。您将在第十章找到更多有关此SID的资讯。
S-1-5-1 Dialup 指出当使用者帐户经由拨接登入Windows 2000系统时,所有使用者帐户自动成为成员的群组。
S-1-5-2 Network 指出当使用者帐户经由网路登入Windows 2000系统时,所有使用者帐户自动成为成员的群组。
S-1-5-3 Batch 指出当使用者帐户经由批次登入的方式登入Windows 2000系统时,所有使用者帐户自动成为成员的群组。
S-1-5-4 Interactive 指出当使用者帐户经由互动式登入Windows 2000系统时,所有使用者帐户自动成为成员的群组。
S-1-5-6 Service 指出当使用者帐户以服务的身分登入Windows 2000系统时,所有使用者帐户自动成为成员的群组。
S-1-5-7 AnonymousLogon 与无效的会议登入结合。
S-1-5-9 ServerLogon 与网域控制站帐户结合。
S-1-5-10 Self(或Principal Self) 充当替代符号,并且只适用于存取群组或使用者帐户的清单。当它出现时,指出存取清单申请的信任成员帐户。
S-1-5-11 Authenticated User 使用者指出一个所有目前被认证的使用者帐户是暗示性成员的群组。
S-1-5-13 Terminal Server 与登入终端服务器的使用者关联。
S-1-5-18 LocalSystem 这个有许多服务皆在其下执行的特别帐户,存在于所有的Windows 2000系统中。有关更多的资讯,请参阅 第十一章 。

而有时候才见面相这些SIDs。熟悉这些体系内建的亲信成员是好的,SID本身的资料结构定义如下:

typedef struct _SID {
    BYTE Revision;
    BYTE SubAuthorityCount;
    SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
    DWORD SubAuthority[ANYSIZE_ARRAY];
}SID;

眼看
单结构的每个成员现在对您来说应该是熟悉的。ANYSIZE_ARRAY定义也1,主要是表示结构不必然就为单一的DWORD代表一个副授权单位以作
结尾。尽管SID结构的自己很理解,它是独「不透明底」资料结构,而且当只有使提供的系函数来操作。这个不透明特性与Microsoft开发人员
在未来改变SID内部结构的即兴。您的软件应该跟这规则。

建立SIDs
 

卿便会呢阳的深信成员建立SIDs,例如Everyone群组。您会经过查询授权单位及信赖成员的值来吗讨论中之深信成员建立一个SID,并且将它传递给AllocateAndInitializeSid函数:

BOOL AllocateAndInitializeSid(
    PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
    BYTE    nSubAuthorityCount,
    DWORD   dwSubAuthority0,
    DWORD   dwSubAuthority1,
    DWORD   dwSubAuthority2,
    DWORD   dwSubAuthority3,
    DWORD   dwSubAuthority4,
    DWORD   dwSubAuthority5,
    DWORD   dwSubAuthority6,
    DWORD   dwSubAuthority7,
    PSID*   ppSid);


应该认识这些参数的用处,值得一提的凡,第一只PidentifierAuthority参数,该参数为而正建立之SID识别授权单位的价。
PidentifierAuthority参数是SID_IDENTIFIER_AUTHORITY的类,被定义也6只各元组的阵列。这看起有些棘
手,但值得庆幸的凡《Platform
SDK》文件定义了这些中的SID授权单位。您应该传递表9-6遭受显示的里一个值,例如SECURITY_NT_AUTHORITY。


亚个值得注意的参数为nSubAuthorityCount,指出您吗SID请求的副授权单位数量。尽管系统现已定义之值
SID_MAX_SUB_AUTHORITIE为15,AllocateAndInitializeSid将独自见面为8或者再少之附带授权单位来起
SIDs。


说明

不管AllocateAndInitializeSid的限,还是当将SIDs当成可也随机大小的景况(即避免静态缓冲器)。


紧接下的八只参数为而新的SID指出从授权单位。我经常怀想掌握干什么Microsoft的开发人员不挑以这些参数合并成DWORD阵列的单一指标。无论如何,您当传递给副授权单位的价和你要之等同多,并且传递0给剩馀的参数。


后一个参数ppSid,值得额外的专注。它吃定义为PSID*,是个对SID指标的指标。和大多数Windows所提供的函数不
同,AllocateAndInitializeSid会指派一个缓冲器给您,而休等待你提供一个缓冲器。被指派的内存位址则经过这个参数传回。


如AllocateAndInitializeSid传回FALSE,表示若特别有或传递了一个超越8之副授权单位数据。因为是函数会指派内存为你,
所以另一个黄的原由或是发出内存不足的情状。假如AllocateAndInitilizeSid执行成功,PSID变数将见面蕴藏一个对准新SID的
指标。当你得SID后,应该将它传递让FreeSid,以使系统可自由SID所利用的内存:

PVOID FreeSid(PSID pSid);

采用AllocateAndInitializeSid,您不仅可以起众所周知的SIDs,也得成立一个若你的软件会鉴别授权单位和辅助授权单位数值的动态SIDs。以下的范例显示了争行使这函数建立一个代表Everyone群组的SID:

PSID BuildEveryoneSid(){
    SID_IDENTIFIER_AUTHORITY auth = SECURITY_WORLD_SID_AUTHORITY;
    PSID pSID = NULL;
    BOOL fSuccess = AllocateAndInitializeSid(&auth, 1,
        SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pSID);
    return(fSuccess ? pSID : NULL);
}

假如您成就了此部数传回之SID后,必须用它的指标传递及FreeSid函数。您可以自由地改者函数,并由改变auth变数的启值,以及传递不同的RID到AllocateAndInitializeSid,以立另一个SID。

信任成员称和二进制的SID转换
 

信任成员帐户名称和二向前制SIDs之间的易是若经常索要实践之实惠工作,系统提供简单单可以实施这些干活儿的函数,这些函数有令人困惑的名号,所以马上是记哪个是孰的特等艺术:

  • 假如你有一个相信成员的帐户名称,但是也用一个二进制的SID,此时您得呼叫LookupAccountName。
     
  • 相反地,假如你发出一个二进制的SID,但是也待一个亲信成员的帐户名称时,您得呼叫LookupAccountSid。
     

要你所见,这些函数的名目即使是你都拥有的新闻。

撷取信任成员的老二进制SID
 

LookupAccountName的函数原型如下:

BOOL LookupAccountName(
    PCTSTR  pszSystemName,
    PCTSTR  pszAccountName,
    PSID    pSid,
    PDWORD  pcbSid,
    PTSTR   pszReferencedDomainName,
    PDWORD  pcbReferencedDomainName,
    PSID_NAME_USE   peUse);

PszSystemName参数是网名称,您想如果于是体系及询问pszAccountName参数中所指定的称号。您得传递NULL给pszSystemName参数,以指出本地机械。


应该在内存中传递一个对准足够为pSid参数所待的SID缓冲器指标,以及一个DWORD位址,包含作为pcbSid参数的缓冲器大小。假如你的缓冲器太
小,系统以盛传失败,而且GetLastError函数会传染回ERROR_INSUFFICIENT_
BUFFER。LookupAccountName也拿经过pcbSid参数为缓冲器应有之轻重填满您提供的DWORD变数。

PszReferenced网域Name及pcbReferenced网域Name分别吗缓冲器接收及帐户相关的网域名称,以及一个对包含大小的DWORD变数指标。即使是免需与信赖成员相关的网域名称,也未克传递NULL给其他一个值。

卿应该传递SID_NAME_USE变数的位址以作为peUse参数。LookupAccount
Name将盛传一个路过peUse指向变数中之价值,它指出已不翼而飞给你的SID类型。表9-9列有这些可能的价值。

 表9-9 SID_NAME_US列举型别类型值
用法
SidTypeUser 指示一个SID给使用者信任成员帐户
SidTypeGroup 指示一个SID给群组信任成员帐户
SidTypeDomain 指示一个代表网域物件的SID
SidTypeAlias 指示一个代表内建群组如管理者群组的SID
SidTypeWellKnownGroup 指示一个SID给众所周知的群组,例如Everyone群组
SidTypeDeletedAccount 指示一个SID给删除的帐户
SidTypeInvalid 指示一个无效的SID
SidTypeUnknown 指示一个未知的SID类型
SidTypeComputer 指示一个SID给网域上的电脑帐户

尽管LookupAccountName取得了电脑名称作为参数,它的物色并无限制于所指定的机。搜寻应该因指示机器的看法来实施。这么说,以下的清单就展示出信任成员的查找顺序:

  1. 明显的SID名称
  2. 在本地机械及内建造及定义之帐户
  3. 夫体系的要紧网域
  4. 给信赖的网域
  5. 在网域树系中的不论一个网域

说明

尽管你可行使LookupAccountName找有明显的SIDs,您要应该时时用AllocateAndInitializeSid来直接建立众所周知的SIDs。


使
您所见到的,信任成员的称号空间在使用者、群组、电脑和网域之间吃分享。尽管系统不同意你运以及其它一个使用者或者群组相同的名称建立平等位使用者或者群组,但相关
统允许使用者要群组拥有和计算机或网域相同之称呼。这生了潜在的题材,因为LookupAccountName会在SID被回传给使用者之前就是污染为电脑。


的软件要为使用者要群组可能会见发跟计算机或网域相同之名负责。处理这情的不过好点子是明摆着地指出电脑名称叫帐户,以作帐户名称的平管辖份。举例来说,
假如电脑以及使用者都取名为「JClark」,而「JClark」帐户已在「JClark」电脑上,以下的程序代码将盛传SID给使用者帐户:

BOOL fRet = LookupAccountName(NULL, "JClark//JClark", 
    &sid, &dwSizeSid, szBuffer, &dwSizeBuf, &use);

撷取信任成员的帐户名称
 

假定你的软件要吗信任成员找来帐户名称,在其早已具备二进制的SID时应当以LookupAccountSid函数:

BOOL LookupAccountSid(
    PCTSTR  pszSystemName,
    PSID    pSid,
    PTSTR   pszName,
    PDWORD  pcbName,
    PTSTR   pszReferencedDomainName,
    PDWORD  pcbReferencedDomainName,
    PSID_NAME_USE   peUse);

PszSystemName参数是若执行搜所当的机器名称。当LookupAccountSid搜寻一个相信成员称时,它见面跟LookupAccountName使用相同之寻顺序与规则。

Psid
是单依靠为而想撷取的与帐户名称相同的今日SID指标。这个SID可以是你建立的,或是系统事先在token以及另外组织面临传回之别一个灵光SID。
PszName及pszReferencedDomainName应该本着你提供用来打系统接受信任成员的称呼以及它的网域名称缓冲器。

旋即
几缓冲器应该要够大,以所有传回的价值;它们的大小会经由指向DWORD变数的指标来传递,pcbName指出经由它所对的缓冲器长度,而
pcbReferencedDomainName则指出经由它对的缓冲器长度。假如你不传递足够大小的缓冲器以起系统接到这些号的话,系统会当及时片个
变数中传唱所待的缓冲器大小。

公当传递SID_NAME_USE变数的位址给peUse,以由系统接受采取的SID。有关SID_NAME_USE之列举型别类型的征,请参阅 

复制SIDs
 

多多网函数会传来SIDs,同时有过多跟安全性相关的函数会期待你建立涵盖SIDs或针对SIDs指标的布局。这不是题材,除了SID结构在长上是可变的以外,系统设计者要求我们以组织作为是休透明底。幸运的凡,系统提供了一个就此来复制SID的函数:

BOOL CopySid(
    DWORD   dwDestinationSidLength,
    PSID    pSidDestination,
    PSID    pSidSource);

其一好用的函数简单地得你的缓冲器长度(以各元组)、一个对目的SID的指标及一个针对性最初SID的指标。


管系统了解它正值复制的SID长度,它仍然要规定不见面受写副过缓冲器的长度。这就是怎么CopySid要求您传递一个尺寸为作第一个参数的原因。
更要紧之是,您将会待懂得被派遣的缓冲器有多要命。可以行使GetLengthSid函数找来因各元组计算的SID长度:

DWORD GetLengthSid(PSID pSid);

乃可以这函数传回之值指派一个缓冲器给你的初SID。

亲笔和第二前行制SID的转移
 

暨了是上,您该都清楚哪尽这些关于SIDs的时要求工作部份。然而,我们本着SIDs的座谈还未完全,除非我报告你何以拿意味着SID的亲笔转换成为因为二进制表示,反之亦然。

以后续讨论前,先证实什么是所谓的「文字SID」。我不讨论代表相信成员帐户名称的字串;而谈论代表二前行制SID结构的字串。

举例来说来说,「S-1-1-0」是一个代表SID的文字SID,它的深信成员帐户名称是Everyone。


储存SID名称到持久的储存器中,例如系统登录,或是在使用者介面中象征一个SID时,文字SIDs会是深有帮助的。您可以用来转换文字SIDs的函
数,分别是ConvertSidToStringSid及ConvertStringSidToSid。以下是它们的函数原型:

BOOL ConvertSidToStringSid(
    PSID        pSid,
    PTSTR*  StringSid);

BOOL ConvertStringSidToSid(
    PCTSTR  StringSid,
    PSID*       ppSid);

当下片个函数都见面叫缓冲器给你,当您做到传回的材料时,释放缓冲器即是公的工作。可以使用LocalFree函数来放这些函数传回的缓冲器。

今天而对系统信任成员帐户的老二迈入制识别资料都发彻底的认识,所以你曾拥有具备本章之前叙述的以本机群组操作成员方法的必要资讯。让咱开谈论着及移除信任成员的权位。

认识权力和帐户权利
 

权力是凭着权利让广大系统分枝的信赖成员(相对之下,指派给信任成员的存取权利虽然定义允许存取系统受到的一定物件)。权限的例证包括登入本机的权、备份文件与目录,以及关闭系统。

另一个着眼权限的不二法门是动保护网函数的平安法。举例来说,某些系统函数,例如LogonUser及InitiateSystemShutdown,要求呼叫的软件要备相当的权杖,否则函数将会执行破产。

发点儿栽而应该了解的权位文字代表。这些文字代表就是Windows使用者介面中展示的爱记名称及软件以的程序名称。每个程序名称还定义在SDK的标头档中。

表9-10排列有了在本书印刷时,Windows
2000遭可用之保有权力。部分的清单在《Platform SDK》文件被。

 表9-10 权限及帐户权利
程序名称 显示的名称 标头档
SeAssignPrimaryTokenPrivilege
SE_ASSIGNPRIMARYTOKEN_NAME
取代一个程序层级的 (处理程序等级的token) WinNT.h
SeAuditPrivilege
SE_AUDIT_NAME
产生安全性稽核 WinNT.h
SeBackupPrivilege
SE_BACKUP_NAME
备份文件及目录 WinNT.h
SeChangeNotifyPrivilege
SE_CHANGE_NOTIFY_NAME
略过往返检查 WinNT.h
SeCreatePagefilePrivilege
SE_CREATE_PAGEFILE_NAME
建立一个分页档 WinNT.h
SeCreatePermanentPrivilege
SE_CREATE_PERMANENT_NAME
建立永久分享的物件 WinNT.h
SeCreateTokenPrivilege
SE_CREATE_TOKEN_NAME
建立一个token物件 WinNT.h
SeDebugPrivilege
SE_DEBUG_NAME
除错程序 WinNT.h
SeEnableDelegationPrivilege
SE_ENABLE_DELEGATION_NAME
信任委派的电脑及使用者帐户 WinNT.h
SeIncreaseBasePriorityPrivilege
SE_INC_BASE_PRIORITY_NAME
增加优先权清单 WinNT.h
SeIncreaseQuotaPrivilege
SE_INCREASE_QUOTA_NAME
增加配额 WinNT.h
SeLoadDriverPrivilege
SE_LOAD_DRIVER_NAME
载入及卸载设备驱动程序 WinNT.h
SeLockMemoryPrivilege
SE_LOCK_MEMORY_NAME
锁住在内存中的页面 WinNT.h
SeMachineAccountPrivilege
SE_MACHINE_ACCOUNT_NAME
增加工作站到网域 WinNT.h
SeProfileSingleProcessPrivilege
SE_PROF_SINGLE_PROCESS_NAME
设定档个别的程序 WinNT.h
SeRemoteShutdownPrivilege
SE_REMOTE_SHUTDOWN_NAME
强迫从远端系统关机 WinNT.h
SeRestorePrivilege E
SE_RESTORE_NAM
回存文件及目录 WinNT.h
SeSecurityPrivilege
SE_SECURITY_NAME
管理稽核及安全性日志 WinNT.h
SeShutdownPrivilege
SE_SHUTDOWN_NAME
关闭系统 WinNT.h
SeSyncAgentPrivilege
SE_SYNC_AGENT_NAME
使目录服务资料同步 WinNT.h
SeSystemEnvironmentPrivilege
SE_SYSTEM_ENVIRONMENT_NAME
修改韧体环境值 WinNT.h
SeSystemProfilePrivilege
SE_SYSTEM_PROFILE_NAME
设定档系统效能 WinNT.h
SeSystemtimePrivilege
SE_SYSTEMTIME_NAME
改变系统时间 WinNT.h
SeTakeOwnershipPrivilege
SE_TAKE_OWNERSHIP_NAME
取得文件或其他物件的所有权 WinNT.h
SeTcbPrivilege
SE_TCB_NAME
扮演操作系统的一部份 WinNT.h
SeUndockPrivilege
SE_UNDOCK_NAME
从母机中移除电脑 WinNT.h
SeUnsolicitedInputPrivilege
SE_UNSOLICITED_INPUT_NAME
接收未经请求的设备输入 WinNT.h
SeBatchLogonRight
SE_BATCH_LOGON_NAME
以批次工作的身分登入 NTSecAPI.h
SeDenyBatchLogonRight
SE_DENY_BATCH_LOGON_NAME
拒绝批次工作的登入 NTSecAPI.h
SeDenyInteractiveLogonRight
SE_DENY_INTERACTIVE_LOGON_NAME
拒绝本机登入 NTSecAPI.h
SeDenyNetworkLogonRight
SE_DENY_NETWORK_LOGON_NAME
拒绝从网路存取这台电脑 NTSecAPI.h
SeDenyServiceLogonRight
SE_DENY_SERVICE_LOGON_NAME
拒绝以服务的身分登入 NTSecAPI.h
SeInteractiveLogonRight
SE_INTERACTIVE_LOGON_NAME
本机登入 NTSecAPI.h
SeNetworkLogonRight
SE_NETWORK_LOGON_NAME
从网路存取这台电脑 NTSecAPI.h
SeServiceLogonRight SE_
SERVICE_LOGON_NAME
以服务的身分登入 NTSecAPI.h

系实际会分别权限和它们的近亲,即帐家权利,他们于同样地使及吊销。如表9-10所出示,权限定义在WinNT.h中,而帐户权利虽然于NTSecAPI.h中定义。

本你对于权力和系统如何表示他们的方应该既发微的认,让我们开始研究于系及派及吊销权限的部份。

LSA函数
 


了产生企划地使权限,您需要熟悉一组称LSA的函数。LSA代表Local Security
Authority,它处理地方机械上的使用者登入及说明。LSA函数可用来作一些以及本章有关的权能指派工作。使用LSA函数的率先步是撷取原则物件的
handle。原则物件代表你将执行帐户管理函数的系统。为了取原则物件的handle,您要呼叫LsaOpenPolicy。

NTSTATUS LsaOpenPolicy(
    PLSA_UNICODE_STRING plsastrSystemName,
    PLSA_OBJECT_ATTRIBUTES  pObjectAttributes,
    ACCESS_MASK DesiredAccess,
    PLSA_HANDLE pPolicyHandle);

这个函数起先看起或产生硌奇怪,因为这些资料型态在另外的Win32套数着不常被采用,所以被我们一个一个地检讨。

PlsastrSystemName是指向LSA_UNICODE_STRING结构的指标,定义如下:

typedef struct _LSA_UNICODE_STRING {
    USHORT  Length;
    USHORT  MaximumLength;
    PWSTR       Buffer;
}LSA_UNICODE_STRING

及Net函数一样,LSA函数只处理Unicode格式的字串。然而,和Net函数不同之是,LSA函数要求为LSA_UNICODE_STRING结构管理有的字串,此布局包括字串长、缓冲器长度和针对缓冲器的指标。


说明

设记Length(指示字串的尺寸)及MaximumLength(指示缓冲器的长短)成员是以各元组的不二法门囤,而未字元。



由LSA_UNICODE_STRING结构的Buffer成员指向的字串没有明了地定义以0作了结。您得择用0来结束字串,但必须确定在配串长的
计算中莫包括无效的最后。请记住当系统传回LSA_UNICODE_STRING给软件时,它不能够要经由Buffer成员指向的字串以0结束。


理LSA_UNICODE_STRING类型可能会见出接触未熟,因为它是以长分隔而未是以0作为分隔。正因如此,LSA_UNICODE_STRING
实际上是吃含有在C++
类别吃。我立了一个号称CLSAStr的型,在本章稍晚叙述的TrusteeMan范例应用程序中会大量地动到其。

只要呼叫LsaOpenPolicy,必须初始化LSA_UNICODE_STRING结构的实例并拿它们对一个富含想操作的权的Unicode字串系统名称。传递NULL以作plsastrSystemName参数值,表示也本土机械。

PobjectAttributes参数指为LSA_OBJECT_ATTRIBUTES结构的实例,在这时候尚不采取,因此要以它的每个成员初始化为0。

DesiredAccess
参数为披露为ACCESS_MASK类型,对诺到32各项第一无号整数。假如你而在系上查看权限的消息,则必须结合这个讨论后底范例中的
POLICY_VIEW_LOCAL_INFORMATION及POLICY_LOOKUP_NAMES。假如你而设定权限资讯,应该使结成
POLICY_CREATE_ACCOUNT存取标记。

最终一个LsaOpenPolicy的参数要求您传递LSA_HANDLE类型变数的位址。执行成功后,系统会将此handle放置到这个变数中开之LSA原则物件。一旦而成功了这条件物件,即应传递此handle到LsaClose函数:

NTSTATUS LsaClose(LSA_HANDLE hObjectHandle);

有的LSA函数皆传回NTSTATUS类型的价,您该拿此价值传递及LsaNtStatusToWinError中:

ULONG LsaNtStatusToWinError(NTSTATUS Status);

LsaNtStatusToWinError函数将NT状态程序代码转变成为熟悉的Win32不当程序代码,就如打GetLastError传回的同等。在变后,成功的呼叫LsaOpenPolicy,以传播一个ERROR_SUCCESS值。

以下的程序代码显示开启一个当网路上,系统名称也「JasonsComputer」之LSA原则物件的适措施:

LSA_OBJECT_ATTRIBUTES  lsaOA = {0};
LSA_UNICODE_STRING  lsastrComputer = {0};
LSA_HANDLE  hPolicy = NULL;

// 电脑名称
WCHAR* pstrName = L"JasonsComputer";

// 设定LSA_OBJECT_ATTRIBUTES结构的大小
lsaOA.Length = sizeof(lsaOA);

// 填入LSA_UNICODE_STRING结构的成员
lsastrComputer.Length = (USHORT) (lstrlen(pstrName) * sizeof(WCHAR));
lsastrComputer.MaximumLength = lsastrComputer.Length + sizeof(WCHAR);
lsastrComputer.Buffer = pstrName;

// 撷取原则的handle
NTSTATUS ntStatus = LsaOpenPolicy(&lsastrComputer, &lsaOA,
    POLICY_VIEW_LOCAL_INFORMATION | POLICY_LOOKUP_NAMES |
    POLICY_CREATE_ACCOUNT, &hPolicy);
ULONG lErr = LsaNtStatusToWinError(ntStatus);
if (lErr != ERROR_SUCCESS){
    // 处理错误
}

兹而已经掌握什么得到LSA原则物件开启的handle,所以你曾预备好起来管理体系上之权。

历数权限
 

历数系统权限的法门来少种植:获得一定信任成员所具有的权力清单,或者请求持有一定权限的深信成员清单。

深信成员有的权位
 

吃咱开讨论哪些收获系统特定的信任成员有的权清单。使用LsaEnumerateAccountRights函数来列举权限:

NTSTATUS LsaEnumerateAccountRights(
    LSA_HANDLE  hPolicy,
    PSID        psidTrustee,
    PLSA_UNICODE_STRING*    pplsastrUserRights,
    PULONG  plCountOfRights);


必须传递一个及POLICY_LOOKUP_NAMES存取一起成立的放条件物件,以作为LSAEnumerateAccountRights的
hPolicy参数。PsidTrustee参数是个因于而想如果列举权限的信任成员SID的指标。您可利用LookupAccountName(在先前
的〈认识SIDs〉一节省被生讨论)从信任成员的帐户名称获得一个SID。这个信任成员好是使用者帐户、群组帐户或者电脑帐户。


应该传递LSA_UNICODE_STRING型态的变数位址给LsaEnumerateAccountRights的
pplsastrUserRights参数。系统会发出LSA_UNICODE_STRING结构的阵列,并指派一个缓冲器包含此阵列,然后以
pplsastrUserRights参数对的变数中放置一个针对性缓冲器的指标。系统会传回plCountOfRights指向的ULONG阵列变数中
的权力号码。

因为系统已了派一个象征你的缓冲器,所以当您做到她经常,必须自由这个缓冲器。传递一个指标到LsaFreeMemory函数的缓冲器中:

NTSTATUS LsaFreeMemory(PVOID pvBuffer);

假如LsaEnumerateAccountRights执行成功了,那么转变的状态程序代码将凡ERROR_SUCCESS;假如帐户没有为派权限,则变动的缪程序代码将会见是ERROR_FILE_NOT_FOUND。


由LsaEnumerateAccountRights传回之阵列元素是LSA_UNICODE_STRING(在原先之〈LSA函数〉一节省中定义)。每
个因素会针对一个暗含代表帐户权利的Unicode字串缓冲器,包括SeDebugPrivilege及
SeEnableDelegationPrivilege等值。您得参照先前之 

尽管LookupPrivilegeDisplayName函数和列举权限并任直接的涉及,但是以此以应干她。这个函数将设计的权力名称,例如SeTcbPrivilege,译成易记的亮名称,在此实例中虽然于译为「扮演作业系统的如出一辙总理份」。

BOOL LookupPrivilegeDisplayName(
    PCTSTR  pszSystemName,
    PCTSTR  pszName,
    PTSTR       pszDisplayName,
    PDWORD  cbDisplayName,
    PDWORD  pLanguageId);

这函数为权力取得系统名称与规划名称,然后再以易记的称呼传到您提供的缓冲器中。


说明

LookupPrivilegeDisplayName不会见也帐户权利传回显示名称。它就吧权力工作。我们当此地的议论并无分这简单种帐户权利的档次,这个主题在第十一回会发出重复完整讨论。您可参考 表9-10 来决定帐户权利是否也权力。假如所讨论的权在WinNT.h标头档中被定义,则它是个权力。如果它们被定义在NTSecAPI.h标头档中,则它只是独钱户权利,并非实际的权力。


以下的范例函数显示怎么列有信任成员有的权位清单。它赢得LSA原则handle及PSID以作它们的参数。

BOOL PrintTrusteePrivs(LSA_HANDLE hPolicy, PSID psid) {
    BOOL fSuccess = FALSE;
    WCHAR szTempPrivBuf[256];
    WCHAR szPrivDispBuf[1024];
    PLSA_UNICODE_STRING plsastrPrivs = NULL;

    __try {
        // 撷取SID的权限阵列
        ULONG lCount = 0;
        NTSTATUS ntStatus = LsaEnumerateAccountRights(hPolicy, psid,
            &plsastrPrivs, &lCount);
        ULONG lErr = LsaNtStatusToWinError(ntStatus);
        if (lErr != ERROR_SUCCESS) {
            plsastrPrivs = NULL;
            __leave;
        }

        ULONG lDispLen = 0;
        ULONG lDispLang = 0;

        for (ULONG lIndex = 0;lIndex < lCount; lIndex++) {
            // 确保0的结束
            lstrcpyn(szTempPrivBuf,
                plsastrPrivs[lIndex].Buffer, plsastrPrivs[lIndex].Length);
            szTempPrivBuf[plsastrPrivs[lIndex].Length] == 0;
            wprintf(L"Programmatic Name: %s/n", szTempPrivBuf);
            // 转译成显示的名称

            lDispLen = 1024; // Size of static Display buffer
            if (LookupPrivilegeDisplayName(NULL, szTempPrivBuf,
                szPrivDispBuf, &lDispLen, &lDispLang))
                wprintf(L"Display Name: %s/n/n", szPrivDispBuf);
        }

        fSuccess = TRUE;
    }
    __finally {
        if (plsastrPrivs) LsaFreeMemory(plsastrPrivs);
    }
    return(fSuccess);
}

享有一定权限的亲信成员
 

第二种撷取Windows
2000网权限资讯的措施吧:经由对LsaEnumerate
AccountsWithUserRight的呼唤请求持有一定权限的深信成员清单。

NTSTATUS LsaEnumerateAccountsWithUserRight(
    LSA_HANDLE  hPolicy,
    PLSA_UNICODE_STRING plsastrUserRight,
    PVOID*  ppvEnumerationBuffer,
    PULONG  CountReturned);

随即
只函数请求一个LSA原则物件的handle,与LsaEnumerateAccountRights很相近。然而,它代表了
LSA_UNICODE_STRING结构的相信成员称,您该传递一个附带权限或帐户权利的设计名称的LSA_UNICODE_STRING结构指
标。

连带
统经由被分派的缓冲器传回信任成员资讯及公的软件面临,以及由此ppvEnumerationBuffer参数传回它的指标。尽管这参数为定义成
PVOID指标,您要当传递指标的位址给PLSA_ENUMERATION_INFORMATION类型之变数,因为系统以为
LSA_ENUMERATION_INFORMATION结构阵列的计传回资讯。假如Windows开发人员定义了
LsaEnumerateAccountsWithUserRight取得正确类型的指标的话,情况将会见再度好,但是他们选取要求一个PVOID指标作为替
代,所以若必须自行将是参数转型。

LSA_ENUMERATION_INFORMATION结构真的非常简单,而且仅包含单一的分子-即一个SID指标:

typedef struct _LSA_ENUMERATION_INFORMATION {
    PSID Sid;
} LSA_ENUMERATION_INFORMATION;


列中元素的多少给染回到CountReturned指向的变数中,为LsaEnumerateAccountsWithUserRight的末尾一个参
数。在传出阵列中之SIDs,经由传递SID到LookupAccountSid中,可被用来起信任成员称。当您做到
LsaEnumerateAccountsWithUserRight传回的缓冲器后,应该要是将它们的指标传递让LsaFreeMemory。

权的派出与移除
 

树单独的软件来列举权限给信任成员帐户的气象是稀罕的。然而,几乎任何一个成立信任成员帐户的软件都必须从帐户被使(或移除)权利。幸运的凡,LSA提供了一定量只简单的函数来实行这些任务。首先,LsaAddAccountRights用来以权力授予信任成员:

NTSTATUS LsaAddAccountRights(
    LSA_HANDLE  hPolicy,
    PSID        psidTrustee,
    PLSA_UNICODE_STRING plsastrUserRights,
ULONG           lCountOfRights);

斯函数很容易使。您得传递开启LSA原则物件的handle,以及对你而改权限的信任成员SID指标(本章先前的议论着曾经涉嫌,您得通呼叫LookupAccountName而落使用者或者群组帐户的SID)。


而,在呼叫LsaAddAccountRights之前,您当建立一个LSA_UNICODE_
STRING结构的阵列,并丰富你想只要相信成员有的权能名称。传递者阵列的指标作为LsaAddAccountRights的
plsastrUserRights参数值。最后,传递阵列中元素的数码被最终一个lCountOfRights参数。

LsaAddAccountRights函数忽略已信任成员具有的其他帐户权利或权限。然而,若阵列中的其余一个权对系吧吧无用的称谓,则会失掉作用。

以下的程序代码提供了一个哪些使SeInteractiveLogonRight帐户权利与SeTcbPrivilege权限给过变数psid指出SID的信任成员。

LSA_UNICODE_STRING lsastrPrivs[2] = { 0 };
lsastrPrivs[0].Buffer = SE_INTERACTIVE_LOGON_NAME;
lsastrPrivs[0].Length =
    lstrlen(lsastrPrivs[0].Buffer) * sizeof(WCHAR);
lsastrPrivs[0].MaximumLength = lsastrPrivs[0].Length + sizeof(WCHAR);
lsastrPrivs[1].Buffer = SE_TCB_NAME;
lsastrPrivs[1].Length =
    lstrlen(lsastrPrivs[1].Buffer) * sizeof(WCHAR);
lsastrPrivs[1].MaximumLength = lsastrPrivs[1].Length + sizeof(WCHAR);
NTSTATUS ntStatus = LsaAddAccountRights(hPolicy, psid,
    lsastrPrivs, 2);
ULONG lErr = LsaNtStatusToWinError(ntStatus);

是用来起信任成员帐户被改换除了权限的函数和LsaAddAccountRights非常相像,称LsaRemoveAccountRights,其函数原型如下:

NTSTATUS LsaRemoveAccountRights(
    LSA_HANDLE  hPolicy,
    PSID        psidTrustee,
    BOOLEAN fAllRights,
    PLSA_UNICODE_STRING plsastrUserRights,
    ULONG       lCountOfRights);

其除了由psidTrustee指示的信任成员被改换除了权利清单及拥有一个叠加参数BooleanfAllRights外,此函数和LsaAddAccountRights一样。

FallRights
可为您打信任成员被移除所有的权限,而休用起信任成员具有的权力清单。假如你传递TRUE给这参数,则plsastrUserRights及
lCountOfRights参数应该分别吗NULL和0。如果您传递FALSE给fAllRights参数,则
LsRemoveAccountRights与LsaAddAccountRights的采取方式同样。

每当
结束LsaRemoveAccountRights的讨论前,我该指出从帐户被移除所有权利的连锁细节。《Platform
SDK》文件中证要你传递TRUE给fAllRights参数的说话,系统以见面由帐户被移除所有的权柄,然后再次于系统面临去这个帐户;然而,这只有从某
个观点来说才是是的。每个执行Windows
2000之系统必须维持一个帐户权限项目之本机资料库(内部实作技术如同本机帐户),即使信任成员乘在其他一样宝机械及,例如网域控制站。
LsaRemoveAccountRights函数不会见于主帐户的网受到删除信任成员帐户(即使是地面帐户);它只是打其的本机资料库中除去帐户权限项目。

成立信任成员的理由
 


结束本章前,我思如果讨论一些信任成员帐户的见识。我们早已讨论过什么立和摧毁使用者及群组帐户以及怎样使权限给这些帐户的情节。此外,也浏览了安康识
别项或SIDs的重要主题。然而,您可能还眷恋了解您的服务器软件必须树立信任成员帐户的来头,简单的话,这是坐不少服务器应用程序从不确立信任成员帐户
以及由现存的相信成员帐户指派或注销权限。

这里发生几乎个因:

  • 范围或者管理资源的存取。这便是若的服务器软件如何以信任成员管理的部份。
     
  • 否使用者建立帐户,以当上入识别的使或也治本现存的使用者如果建立群组帐户。尽管就是立信任成员帐户常见的原委,但服务器软件并非如此。MMC或任何管理之家伙通常会管理这些函数。
     

下同样回我们以讨论信任成员与康宁物件存取权利之间的关联。第十一段将谈话到公的服务器软件可用来代表客户端或其它随意选取的信赖成员帐户行为之点子,您吗以学会经由使用第二只信任成员帐户调整现存信任成员权的方。


着这些主题的揭秘,您将学会用Windows环境面临不过得之各种技能,并因为重发生创造性的法子来限制及增长对物件的存取,如果必要的话,使你的服务器软件拥
有树信任成员帐户的权能是异常重大之。在属下去的几章节中讨论到这些主题时,我将提出由您的服务器软件建立唯一信任成员的熨帖案例。

TrusteeMan范例应用程序
 

TrusteeMan
范例应用程序(「09
TrusteeMan.exe」)示范Net函数的以以及因此来确立及保管使用者及群组帐户,与差及吊销系统权限的LSA函数。这个应用程序的原始码及文
件,存放于随书光碟中之09-TrusteeMan目录下。图9-2显示了TrusteeMan范例应用程序的使用者介面。

 

 图9-2 TrusteeMan范例应用程序之使用者介面


用性是覆写TrusteeMan范例应用程序的对象。因为坐众多端来说,必须追究与了解安全性的内容,而一个可用之家伙能帮助而浏览系统的特点。这个范
例应用程序可让你尽情地确立使用者及群组帐户。也不过吃你修改群组的分子,并给及否决权限给系统及之信任成员帐户。您得输入而采取的微机名称还在有足
够权利的任何系统上管理信任成员。


说明

当你使用TrusteeMan建立使用者帐户时,应用程序会以「Pass2000」作为你新帐户的密码。这个密码简化了使用者介面并汇总在重要之主题上。假如你是系的企业主,您可利用MMC嵌入式管理单元为使用者帐户手动地设定密码。


提议您花来时日看TrusteeMan范例应用程序,以习Windows
2000的深信成员管理的运作方式。本书其馀的区块皆假得您见面动用TrusteeMan、MMC嵌入式管理单元,或任何管理使用者帐户及派出权限的工具。

TrusteeMan范例应用程序除了是单有效的工具外,它的原始码也提供了不少有关信任成员管理之Net及LSA函数功能参考。这个范例应用程序使用Net函数执行应用程序的左窗格或亲信成员侧,而用LSA函数实作应用程序的权利虽然于右边窗格或权限侧。

本条范例也也编制信任成员清单实作一个可重覆使用的通用对话方块。此范例使用这个对话方块来管理群组帐户及特定权限的主人。系统绝非也之提供内建的介面,所以当范例中含一个。

 表9-10 中存有可污染回的权能清单内容。表9-9 。TrusteeMan范例应用程序 。表9-1 中所讨论的LOCALGROUP_INFO_*
结构集。您得传递0或者1因作之函数的level值。这片个组织的定义如下:

分享到:

  • 上一篇:10.
    存取控制
  • 下一篇:12.
    安然无恙连接

相关文章