微软提供了MSV1_0验证包用于不需要定制验证的本地机器登录。LSA调用MSV1_0验证包来处理由GINA收集的登录数据供Winlogon登录过程使用。MSV1_0检查本地安全帐号管理器(SAM)数据库来决定登录数据是否属于安全主体, 然后返回登录的结果给LSA。
MSV1_0 也支持域登录。MSV1_0 使用pass-through 验证处理登录,在下面的图例中说明:
在pass-through验证中,本地机器上的MSV1_0实例使用Netlogon 服务来调用域控制器上的 MSV1_0实例。域控制器上的 MSV1_0实例检查域控制器的SAM数据库然后返回登录结果到本地机器上的 MSV1_0实例。本地版本的 MSV1_0转发登录结果到本地的LSA实例。
如果域控制器不可用,并且LSA缓存了用户证书, MSV1_0的本地实例就可以使用缓存的数据来验证登录数据。
MSV1_0验证包也支持子验证包( subauthentication packages)。子验证包是一个DLL,它可以部分替代MSV1_0验证包所使用的验证和确认标准。
MSV1_0 验证包定义了一个primary credentials key/string 对。primary credentials string保存了源自登录时所提供的数据的证书。它包括了用户名和大小写敏感和不敏感两种形式的用户密码。
Subauthentication Packages
随Windows提供的验证报支持定制使用子验证包。子验证包是一个DLL,它可以部分提供或替代主验证包所使用的验证和确认标准。例如,一个精细的服务器可能提供一个子验证包,它可以用不同的算法处理用户密码或以不同的格式指明工作站的限制。
Creating Subauthentication Packages
一些验证包,像是MSV1_0 和 Kerberos, 支持子验证包。一个子验证包必须实现的接口依赖于它所支持的那个验证包。支持MSV1_0的子验证包必须支持 Msv1_0SubAuthenticationRoutine、Msv1_0SubAuthenticationFilter 这两个函数。支持Kerberos的验证包必须支持Msv1_0SubAuthenticationFilter函数。
在你完成一个子验证包之后,在可以使用之前你必须把它添加到注册表中。注册的细节是由验证包所指明的,但典型的来说是通过在验证包的键值下添加一个子键来实现的。
Registering Subauthentication Packages
每一个子验证DLL都会在从0到255的范围内被赋予一个DLL序号。DLL序号用于将LsaLogonUser调用和相应的子验证DLL关联起来。DLL序号零被保留,用于域控制器子验证过滤器(SubAuthentication Filter)。在MSV1_0或Kerberos完成正常的密码或验证之后,这个DLL还允许验证包在域控制器上做一些额外的确认工作。DLL序号1到127由微软保留。序号128到254可供独立软件供应商使用。软件供应商可由微软赋予一个DLL序号。由微软注册一个子验证包可以防止在一个系统上安装多个子验证包时,验证包ID之间发生冲突。
微软不会将255赋予任何子验证DLL。如果你开发了一个子验证DLL,它仅用在你的公司或设施上,推荐使用序号255。在这种情况下,就不需要从微软获取一个子验证DLL序号。
在拥有了一个DLL之后,你就可以把它注册到相关的验证包的键值之下。
MSV1_0子验证包在注册表中的位置是:
HKEY_LOCAL_MACHINE/System/CurrentControlSet/Control/Lsa/MSV1_0
Kerberos子验证包在注册表中的位置是:
HKEY_LOCAL_MACHINE/System/CurrentControlSet/Control/Lsa/Kerberos
如果所需的键值不存在,你必须创建它。在前述的键之下,创建名为“AuthN”的键值,在这里“N”为DLL序号。(例如,Auth255).
AuthN 键值为 REG_SZ类型的数据,并且必须指明子验证包DLL的名称。DLL必须在不同的DLL加载路径中。
验证包在首次需要子验证包时加载该DLL.
Creating Custom Authentication Packages
如果你正在支持一个定义了一个新的登录过程的系统,像是视网膜扫描或是声音识别,你必须创建一个定制验证包来分析新的登录数据,并且决定是否接受用户证书。你也可以创建一个新的验证包,它使用标准登录数据但是实现了新的安全协议。
LSA当从一个登录程序接收到一个验证服务请求时,会调用由验证包实现的函数。当一个用户尝试登录到系统时,验证报必须依照文件中的证书信息来检查用户的登录数据。随Windows一起提供的验证包这些信息存储在SAM数据库中或是活动目录中(依赖于OS的版本和配置)。
系统不允许不是OS一部分的程序直接的访问已存在的证书数据,如果这样做的话,可能会造成安全隐患(security risk)。你的定制验证包必须调用MSV1_0来访问用户的验证信息。你的验证包调用MSV1_0来执行初始验证并且创建一个登录会话。如果初始验证成功的话,你的验证包接下来就可以执行附加的处理来支持新的登录协议或算法,然后将验证结果返回到LSA。下面的图示显示了这个过程:
定制验证包和MSV1_0均支持验证包接口。LSA调用定制包内的验证包接口,定制包又会调用MSV1_0内的函数。定制的验证包必须能够传递引入的登录数据,这些数据使用由MSV1_0支持的数据结构。传递到MSV1_0的结构应该在登录进程的地址空间中分配,而不是LSA的地址空间中。
MSV1_0处理登录请求然后返回结果(如果成功的话,返回LUID)给定制包。定制包然后就可以执行额外的验证检查,像是决定扫描的指纹是否与用户帐号匹配,然后将成功或失败的结果返回给LSA。如果你的定制包撤销一个MSV1_0已通过的登录,它就必须调用DeleteLogonSession函数来删除由MSV1_0创建的登录会话。
Registering Authentication Packages
在你已经建立好验证包之后,你必须为LSA注册它。在下面的注册表值中添加你的验证包名称:
HKEY_LOCAL_MACHINE/System/CurrentControlSet/Control/Lsa/Authentication Packages
这个注册表入口包含了已安装的验证包DLL的名称列表(不需要“.DLL"扩展名)。这个列表为REG_MULTI_SZ类型,所以在每个验证包名字之间有空字符(‘/0')。下一次系统启动的时候,LSA会检查这个列表并且加载你的验证包。
典型的情况下,验证包DLL保存在 %systemroot%/system32 目录中。你如果将DLL保存在其他地方,你必须在注册表中指明DLL的全路径。
Using LSA from a Logon Application
LSA提供一些像是定制的GINA这样的登录进程可以调用的函数来验证用户。为了调用这些函数,你的进程必须具有SeTcbPrivilege(trusted computing base)特权。
在请求验证服务之前,你的登录进程必须通过调用LsaRegisterLogonProcess来建立一个到LSA的连接。这个函数建立一个到LSA的连接并且返回一个供之后用来对LSA调用的句柄。当到LSA的连接不再需要时,调用LsaDeregisterLogonProcess。
得到句柄之后,你可以调用LsaLogonUser来尝试登录用户到系统中。在这个调用期间,你需要指明验证包的标识符来处理登录请求。如果知道验证报的名称,你可以通过调用LsaLookupAuthenticationPackage来查找它的标识符。
如果用户成功登录,LSA会将包含用户安全信息的令牌(token)返回到你的登录进程。你的登录进程可以使用这个令牌来检查访问许可、为用户创建进程,和需要令牌的其他操作。For more information, see Access Control and the CreateProcessAsUser and AccessCheck functions documented in the Platform SDK.
除了标准验证函数,验证包也可以提供验证包指明的服务。你的程序可以通过调用LsaCallAuthenticationPackage函数与验证包通讯来请求一个服务。在调用LsaCallAuthenticationPackage过程中所用到的输入输入缓冲区的内容和格式只针对验证包;LSA不会处理数据而只是简单的转发到验证包中。 For more information, see the LsaCallAuthenticationPackage reference page.
注意:典型情况下,如果你已经写了一个定制的GINA来处理非标准的登录数据,你必须也写一个可以处理数据的定制验证包。