如何将额外的参数传递给Windows Server 2k8R2 \ 2K3上的SubAuthentication DLL(代码C ++) [英] How to pass extra parameter to SubAuthentication DLL on Windows Server 2k8R2 \2K3( Code C++)
问题描述
Hi, 我已经开发了用于验证身份验证的子身份验证模块(SubAuth.dll)用户,当通过客户端Windows PC或客户端程序登录时.SubAuth.dll
该模块具有Msv1_0SubAuthenticationFilter功能,已实现并导出该功能用于子身份验证.
I have developed a sub-authentication module (SubAuth.dll) for authenticating the user, when logs in through client windows PC or client program. The SubAuth.dll
module has a function Msv1_0SubAuthenticationFilter implemented and exported for sub-authentication purpose.
在HKEY_LOCAL_MACHINE \ System \ CurrentControlSet \ Control下创建了注册表项\ Lsa \ Kerberos
Registry entry have been created under HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa\Kerberos
名称-> Auth0 Value-> SubAuth 作为Auth0,其值设置为DLL的完整路径.重新启动DC SubAuth.dll后,其注册正确,并且我能够看到初始日志文件,内容如下
当任何用户尝试登录到该域时,将加载该模块.对MSV1_0软件包进行了相同的更改. as Auth0 with value set as the complete path of the DLL. After reboot of DC SubAuth.dll is registered properly and I am able to see initial log file saying that following
module is loaded when any user try to logon to that domain. Same changes are done for MSV1_0 package. 现在我遇到了问题.我没有找到其他文档,没有详细解释如何将附加值传递给subauth模块.如何将附加值传递给subauth模块. 我们想知道:
We would like to know:
*有什么我想念的要启用我们的子项吗? -身份验证模块?
* Is there anything that I have missed out for enabling our sub-authentication module?
*是否可以将多余的参数\值传递给子- 32 \ 64位Windows Server计算机上的身份验证DLL
* Is it possible to Pass Extra Parameter\Value to sub-authentication DLL on 32\64 bit Windows Server Machine
在这方面的任何帮助,因为我是该领域的新手在Windows操作系统上进行身份验证.
Any help in this regard as I am new to this field of Authentication on Windows OS.
我创建了一个示例程序,该程序充当客户端并生成登录请求以调用subauth .dll,但是当我尝试通过此用户登录时出现以下错误
示例客户端程序. I created a sample program which act as client and generates logon request to call subauth.dll but I am getting following error when I try to logon a user through this
sample client program. 错误:
3-> LsaLogonUser失败:找不到指定的过程. OR 错误:
3-> LsaLogonUser失败:找不到指定的模块. 用于登录的客户端示例程序. HANDLE LogonFun( const
wchar_t
* pszUserName, const
wchar_t
* pszUserPassword, const
char_t
* pszDomain,
int pChoice) const
wchar_t
* pszUserName, const
wchar_t
* pszUserPassword, const
char_t
* pszDomain,
int pChoice) { .. . OpenProcessToken(procHandle,TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,& hToken);
如果(SetPrivilege(hToken,SE_TCB_NAME,1))
if (SetPrivilege(hToken,SE_TCB_NAME, 1 ))
wprintf(L &"SetPrivilege -ENABLED \ n" );
wprintf(L"SetPrivilege -ENABLED\n" );
u_si(& UserName,(常量
wchar_t *)pszUserName);
u_si(&UserName,(const
wchar_t * )pszUserName);
u_si(& Domain,(常量
wchar_t *)pszDomain);
u_si(&Domain,(const
wchar_t * )pszDomain); u_si(& Workstation,L "10.77.68.74" ); u_si(&Workstation,L"10.77.68.74" );
u_si(& Password,(常量
wchar_t *)pszUserPassword);
u_si(&Password,(const
wchar_t * )pszUserPassword);
str2buf2lsa(origin.str,origin.buf,"User32" );
str2buf2lsa (origin.str, origin.buf, "User32" ); str2lsa(LogonProcName,
&; User32"; ); str2lsa (LogonProcName,
"User32" ); cbUserName =(USHORT)(wcslen(UserName.缓冲) *
sizeof (WCHAR)); cbUserName = (USHORT)(wcslen(UserName.Buffer) *
sizeof (WCHAR));
cbDomain =(USHORT)(wcslen(Domain.Buffer)* sizeof (WCHAR));
cbDomain = (USHORT)(wcslen(Domain.Buffer) * sizeof (WCHAR));
cbWorkstation =(USHORT)(wcslen(Workstation.Buffer)*
sizeof (WCHAR));
cbWorkstation = (USHORT)(wcslen(Workstation.Buffer) *
sizeof (WCHAR));
cbPassword =(USHORT)(wcslen(Password.Buffer)* sizeof (WCHAR));
cbPassword = (USHORT)(wcslen(Password.Buffer) * sizeof (WCHAR)); _ checknterr(L " 1- > LsaRegisterLogonProcess" ,LsaRegisterLogonProcess(& LogonProcName,& hToken,& SecMode)); _checknterr(L"1->LsaRegisterLogonProcess" , LsaRegisterLogonProcess(&LogonProcName, &hToken, &SecMode)); if
(pChoice == 1) si(& pkgName,MICROSOFT_KERBEROS_NAME_A); //MICROSOFT_KERBEROS_NAME_A
else
else
_si(& pkgName,MSV1_0_PACKAGE_NAME); //MSV1_0_PACKAGE_NAME
_si(&pkgName, MSV1_0_PACKAGE_NAME);//MSV1_0_PACKAGE_NAME
_ checknterr(L " 2- > LsaLookupAuthenticationPackage" ,
LsaLookupAuthenticationPackage(hToken,& pkgName,& authnPkg));
LsaLookupAuthenticationPackage(hToken,&pkgName, &authnPkg)); wprintf(L " authnPkg = %u \ n"",authnPkg); wprintf(L"authnPkg=%u \n" , authnPkg); hHeap = GetProcessHeap();
//进程堆句柄 hHeap=GetProcessHeap();
// process heap handle AuthInfoSize_MSV =
sizeof (MSV1_0_SUBAUTH_LOGON)+ AuthInfoSize_MSV =
sizeof (MSV1_0_SUBAUTH_LOGON) +
cbUserName + sizeof (UNICODE_NULL)+
cbUserName + sizeof (UNICODE_NULL) +
cbDomain + sizeof (UNICODE_NULL)+
cbDomain + sizeof (UNICODE_NULL) +
cbWorkstation + sizeof (UNICODE_NULL);
cbWorkstation + sizeof (UNICODE_NULL) ; AuthInfoBuf_MSV = HeapAlloc(hHeap,
HEAP_ZERO_MEMORY,
HEAP_ZERO_MEMORY,
AuthInfoSize_MSV);
AuthInfoSize_MSV);
pMsvAuthInfo =(PMSV1_0_SUBAUTH_LOGON)AuthInfoBuf_MSV;
pMsvAuthInfo = (PMSV1_0_SUBAUTH_LOGON)AuthInfoBuf_MSV;
如果(pMsvAuthInfo == NULL)
if (pMsvAuthInfo == NULL)
{
{
wprintf(L &"DEBUG-fillSubauthLogon-ERROR_01 \ n" );
wprintf(L"DEBUG-fillSubauthLogon-ERROR_01\n" );
返回 NULL;
return NULL;
}
}
其他
else
wprintf(L &"DEBUG-fillSubauthLogon-SUCCESS_01 \ n" );
wprintf(L"DEBUG-fillSubauthLogon-SUCCESS_01\n" ); pMsvAuthInfo-> MessageType = MsV1_0SubAuthLogon; pMsvAuthInfo-> UserName.Length = cbUserName;
pMsvAuthInfo-> UserName.MaximumLength = cbUserName +
pMsvAuthInfo->UserName.MaximumLength = cbUserName +
sizeof (UNICODE_NULL);
sizeof (UNICODE_NULL);
pMsvAuthInfo-> UserName.Buffer =(PWSTR)(pMsvAuthInfo + 1);
pMsvAuthInfo->UserName.Buffer = (PWSTR)(pMsvAuthInfo + 1);
wcscpy(pMsvAuthInfo-> UserName.Buffer,UserName.Buffer);
wcscpy(pMsvAuthInfo->UserName.Buffer, UserName.Buffer);
//
//
//将域名复制到身份验证缓冲区中
// Copy the domain name into the authentication buffer
//
//
pMsvAuthInfo-> LogonDomainName.Length = cbDomain;
pMsvAuthInfo->LogonDomainName.Length = cbDomain;
pMsvAuthInfo-> LogonDomainName.MaximumLength = cbDomain +
pMsvAuthInfo->LogonDomainName.MaximumLength = cbDomain +
sizeof (UNICODE_NULL);
sizeof (UNICODE_NULL);
wprintf(L &"DEBUG-fillSubauthLogon-SUCCESS_03 \ n" );
wprintf(L"DEBUG-fillSubauthLogon-SUCCESS_03\n" );
pMsvAuthInfo-> LogonDomainName.Buffer =(PWSTR)
pMsvAuthInfo->LogonDomainName.Buffer = (PWSTR)
((PBYTE)(pMsvAuthInfo-> UserName.Buffer)+
((PBYTE)(pMsvAuthInfo->UserName.Buffer) +
pMsvAuthInfo-> UserName.MaximumLength);
pMsvAuthInfo->UserName.MaximumLength);
wcscpy(pMsvAuthInfo-> LogonDomainName.Buffer,Domain.Buffer);
wcscpy(pMsvAuthInfo->LogonDomainName.Buffer, Domain.Buffer);
//
//
//将工作站复制到身份验证缓冲区中
// Copy the workstation into the authentication buffer
//
//
pMsvAuthInfo-> Workstation.Length = cbWorkstation;
pMsvAuthInfo->Workstation.Length = cbWorkstation;
pMsvAuthInfo-> Workstation.MaximumLength = cbWorkstation +
pMsvAuthInfo->Workstation.MaximumLength = cbWorkstation +
sizeof (UNICODE_NULL);
sizeof (UNICODE_NULL);
pMsvAuthInfo-> Workstation.Buffer =(PWSTR)
pMsvAuthInfo->Workstation.Buffer = (PWSTR)
((PBYTE)(pMsvAuthInfo-> LogonDomainName.Buffer)+
((PBYTE)(pMsvAuthInfo->LogonDomainName.Buffer) +
pMsvAuthInfo-> LogonDomainName.MaximumLength);
pMsvAuthInfo->LogonDomainName.MaximumLength);
wcscpy(pMsvAuthInfo-> Workstation.Buffer,Workstation.Buffer);
wcscpy(pMsvAuthInfo->Workstation.Buffer, Workstation.Buffer);
wprintf(L &"DEBUG-fillSubauthLogon-SUCCESS_04 \ n" );
wprintf(L"DEBUG-fillSubauthLogon-SUCCESS_04\n" );
pMsvAuthInfo-> AuthenticationInfo1.Length = 0x00;
pMsvAuthInfo->AuthenticationInfo1.Length = 0x00;
pMsvAuthInfo-> AuthenticationInfo1.MaximumLength = 0x00;
pMsvAuthInfo->AuthenticationInfo1.MaximumLength = 0x00;
pMsvAuthInfo-> AuthenticationInfo1.Buffer = 0x00;
pMsvAuthInfo->AuthenticationInfo1.Buffer = 0x00;
pMsvAuthInfo-> AuthenticationInfo2.Length = 0x00;
pMsvAuthInfo->AuthenticationInfo2.Length = 0x00;
pMsvAuthInfo-> AuthenticationInfo2.MaximumLength = 0x00;
pMsvAuthInfo->AuthenticationInfo2.MaximumLength = 0x00;
pMsvAuthInfo-> AuthenticationInfo2.Buffer = 0x00;
pMsvAuthInfo->AuthenticationInfo2.Buffer = 0x00;
wprintf(L &"DEBUG-fillSubauthLogon-SUCCESS_05 \ n" );
wprintf(L"DEBUG-fillSubauthLogon-SUCCESS_05\n" );
pMsvAuthInfo-> ParameterControl = MSV1_0_SUBAUTHENTICATION_DLL;
pMsvAuthInfo->ParameterControl = MSV1_0_SUBAUTHENTICATION_DLL;
//pMsvAuthInfo-> ParameterControl = MSV1_0_UPDATE_LOGON_STATISTICS | MSV1_0_DONT_TRY_GUEST_ACCOUNT;
//pMsvAuthInfo->ParameterControl = MSV1_0_UPDATE_LOGON_STATISTICS|MSV1_0_DONT_TRY_GUEST_ACCOUNT;
//pMsvAuthInfo-> ParameterControl = MSV1_0_CLEARTEXT_PASSWORD_ALLOWED;//| MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT | MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
//pMsvAuthInfo->ParameterControl = MSV1_0_CLEARTEXT_PASSWORD_ALLOWED;//|MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT|MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT;
wprintf(L " DEBUG-fillSubauthLogon-SUCCESS_06 \ n" );
wprintf(L"DEBUG-fillSubauthLogon-SUCCESS_06\n" );
pMsvAuthInfo-> SubAuthPackageId = 0;
pMsvAuthInfo->SubAuthPackageId = 0;
wprintf(L &"DEBUG-fillSubauthLogon-SUCCESS_07 \ n" );
wprintf(L"DEBUG-fillSubauthLogon-SUCCESS_07\n" );
wprintf(L &"DEBUG-fillSubauthLogon END \ n" );
wprintf(L"DEBUG-fillSubauthLogon END\n" ); _ checknterr(L " 3- > LsaLogonUser" ,LsaLogonUser(hToken, _checknterr(L"3->LsaLogonUser" , LsaLogonUser(hToken,
(PLSA_STRING)& LogonProcName,
(PLSA_STRING)&LogonProcName,
网络
Network,
authnPkg,
authnPkg,
pMsvAuthInfo,AuthInfoSize_MSV,
pMsvAuthInfo, AuthInfoSize_MSV,
0,& tokenSource,(PVOID *)& profile,& cbProfile,& logonId,
0, &tokenSource,(PVOID *)&profile, &cbProfile,&logonId,
& htok,& quotaLimits,& subStatus));
&htok,"aLimits,&subStatus));
//清理
// clean up
_checknterr(L 结束-> LsaDeregisterLogonProcess"; ,LsaDeregisterLogonProcess(hToken));
_checknterr(L"end-->LsaDeregisterLogonProcess" , LsaDeregisterLogonProcess(hToken) );
HeapFree(hHeap,HEAP_ZERO_MEMORY,AuthInfoBuf_MSV);
HeapFree(hHeap,HEAP_ZERO_MEMORY,AuthInfoBuf_MSV);
LsaFreeReturnBuffer(profile);
LsaFreeReturnBuffer(profile);
如果(SetPrivilege(hToken,SE_TCB_NAME,0))
if ( SetPrivilege(hToken,SE_TCB_NAME, 0 ) )
wprintf(L &"Inside SetPrivilege-DISABLED \ n" );
wprintf(L"Inside SetPrivilege-DISABLED\n" );
CloseHandle(hToken);
CloseHandle(hToken);
wprintf(L " DEBUG-END \ n" );
wprintf(L"DEBUG-END\n" );
返回 htok;
return htok;
} int main() { .. //我的代码 //在此处调用LogonFun功能 LogonFun(UserName,UserPass,Domain,Choice); } SubAuth.dll的代码
Code for SubAuth.dll
{ #include
< windows.h>
#include
<windows.h>
#include
< lmcons.h>
#include
<lmcons.h>
#include
< lmaccess.h>
#include
<lmaccess.h>
#include
< lmapibuf.h>
#include
<lmapibuf.h>
#include
< subauth.h>
#include
<subauth.h>
#include
< windef.h>
#include
<windef.h>
#include
< stdio.h>
#include
<stdio.h>
#include
< time.h>
#include
<time.h>
静态
BOOL WriteLogFile(LPTSTR String); #ifdef
_MANAGED #pragma managed(push, off) #endif BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
DWORD ul_reason_for_call,
LPVOID lpReservedkjkk
LPVOID lpReservedkjkk
)
) {
switch (ul_reason_for_call)
switch (ul_reason_for_call)
{
{
case DLL_PROCESS_ATTACH:
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
case DLL_PROCESS_DETACH:
break ;
break ;
}
}
return TRUE;
return TRUE; } #ifdef
_MANAGED #pragma managed(pop) #endif #define
STATUS_NOT_IMPLEMENTED
((NTSTATUS)0xC0000002L) #define
STATUS_NOT_IMPLEMENTED
((NTSTATUS)0xC0000002L) #define
SUBAUTH_PKG_NAME
"subauth" #define
SUBAUTH_PKG_NAME
"subauth" NTSTATUS NTAPI Msv1_0SubAuthenticationFilter (
IN NETLOGON_LOGON_INFO_CLASS LogonLevel,
IN NETLOGON_LOGON_INFO_CLASS LogonLevel,
IN PVOID LogonInformation,
IN PVOID LogonInformation,
IN ULONG Flags,
IN ULONG Flags,
IN PUSER_ALL_INFORMATION UserAll,
IN PUSER_ALL_INFORMATION UserAll,
OUT PULONG WhichFields,
OUT PULONG WhichFields,
OUT PULONG UserFlags,
OUT PULONG UserFlags,
OUT PBOOLEAN Authoritative,
OUT PBOOLEAN Authoritative,
OUT PLARGE_INTEGER LogoffTime,
OUT PLARGE_INTEGER LogoffTime,
OUT PLARGE_INTEGER KickoffTime
OUT PLARGE_INTEGER KickoffTime ) { NTSTATUS Status;
SYSTEMTIME CurrentTime;
SYSTEMTIME CurrentTime;
WCHAR buf[2048];
WCHAR buf[2048];
PNETLOGON_LOGON_IDENTITY_INFO Identity =
PNETLOGON_LOGON_IDENTITY_INFO Identity =
(PNETLOGON_LOGON_IDENTITY_INFO)LogonInformation;
(PNETLOGON_LOGON_IDENTITY_INFO)LogonInformation;
PUSER_ALL_INFORMATION UserInfo =
PUSER_ALL_INFORMATION UserInfo =
(PUSER_ALL_INFORMATION)UserAll;
(PUSER_ALL_INFORMATION)UserAll;
time_t t1;
time_t t1;
time(&t1);
time(&t1);
FILE *f =fopen("c:\\SubAuth.log" ,"a+" );
FILE *f =fopen("c:\\SubAuth.log" ,"a+" );
fprintf(f, "Msv1_0SubAuthenticationFilter->Started at %s\n" , ctime(&t1));
fprintf(f, "Msv1_0SubAuthenticationFilter->Started at %s\n" , ctime(&t1));
fflush(f);
fflush(f);
fprintf(f, "Msv1_0SubAuthenticationFilter->Finished\n" );
fprintf(f, "Msv1_0SubAuthenticationFilter->Finished\n" );
fflush(f);
fflush(f);
//fclose(f);
//fclose(f);
Status = STATUS_SUCCESS;
Status = STATUS_SUCCESS;
*Authoritative = TRUE;
*Authoritative = TRUE;
*UserFlags = 0;
*UserFlags = 0;
*WhichFields = 0;
*WhichFields = 0;
GetLocalTime( &CurrentTime );
GetLocalTime( &CurrentTime );
if (!Identity) {
if (!Identity) {
WriteLogFile(TEXT("No identity\r\n" ));
WriteLogFile(TEXT("No identity\r\n" ));
return Status;
return Status;
}
}
swprintf_s(buf, RTL_NUMBER_OF(buf),
swprintf_s(buf, RTL_NUMBER_OF(buf),
L"%02d/%02d/%d %02d:%02d:%02d: Logon (level=%d) %wZ\\%wZ (%wZ) from %wZ \r\n" ,
L"%02d/%02d/%d %02d:%02d:%02d: Logon (level=%d) %wZ\\%wZ (%wZ) from %wZ \r\n" ,
CurrentTime.wMonth, CurrentTime.wDay, CurrentTime.wYear,
CurrentTime.wMonth, CurrentTime.wDay, CurrentTime.wYear,
CurrentTime.wHour, CurrentTime.wMinute, CurrentTime.wSecond,
CurrentTime.wHour, CurrentTime.wMinute, CurrentTime.wSecond,
LogonLevel,
LogonLevel,
&Identity->LogonDomainName, &Identity->UserName,
&Identity->LogonDomainName, &Identity->UserName,
&UserAll->FullName, &Identity->Workstation
&UserAll->FullName, &Identity->Workstation
//&Identity->LogonId,
//&Identity->LogonId,
//&Identity->ParameterControl
//&Identity->ParameterControl
);
);
WriteLogFile(buf);
WriteLogFile(buf);
if (LogoffTime) {
if (LogoffTime) {
LogoffTime->HighPart = 0x7FFFFFFF;
LogoffTime->HighPart = 0x7FFFFFFF;
LogoffTime->LowPart = 0xFFFFFFFF;
LogoffTime->LowPart = 0xFFFFFFFF;
}
}
if (KickoffTime) {
if (KickoffTime) {
KickoffTime->HighPart = 0x7FFFFFFF;
KickoffTime->HighPart = 0x7FFFFFFF;
KickoffTime->LowPart = 0xFFFFFFFF;
KickoffTime->LowPart = 0xFFFFFFFF;
}
}
switch ( LogonLevel ) {
switch ( LogonLevel ) {
case NetlogonInteractiveInformation:
case NetlogonInteractiveInformation:
WriteLogFile(L"NetlogonInteractiveInformation\r\n" );
WriteLogFile(L"NetlogonInteractiveInformation\r\n" );
break ;
break ;
case NetlogonServiceInformation:
case NetlogonServiceInformation:
WriteLogFile(L"NetlogonServiceInformation\r\n" );
WriteLogFile(L"NetlogonServiceInformation\r\n" );
break ;
break ;
case NetlogonNetworkInformation:
case NetlogonNetworkInformation:
//
//
//If you care you can determine what to do here
// If you care you can determine what to do here
//
//
*Authoritative = FALSE;
*Authoritative = FALSE;
if (LogoffTime) {
if (LogoffTime) {
LogoffTime->HighPart = 0x7FFFFFFF;
LogoffTime->HighPart = 0x7FFFFFFF;
LogoffTime->LowPart = 0xFFFFFFFF;
LogoffTime->LowPart = 0xFFFFFFFF;
}
}
if (KickoffTime) {
if (KickoffTime) {
KickoffTime->HighPart = 0x7FFFFFFF;
KickoffTime->HighPart = 0x7FFFFFFF;
KickoffTime->LowPart = 0xFFFFFFFF;
KickoffTime->LowPart = 0xFFFFFFFF;
}
}
WriteLogFile(L"NetlogonNetworkInformation\r\n" );
WriteLogFile(L"NetlogonNetworkInformation\r\n" );
break ;
break ;
default :
default :
WriteLogFile(L"STATUS_INVALID_INFO_CLASS-\r\n" );
WriteLogFile(L"STATUS_INVALID_INFO_CLASS-\r\n" );
return STATUS_INVALID_INFO_CLASS;
return STATUS_INVALID_INFO_CLASS;
}
}
fclose(f);
return Status;
return Status; } Any pointers to this problem will be really useful. 谢谢. SSBhatia, SSBhatia, I tried to help you, did the following: I tried to help you, did the following: (1) I compiled your code into SubAuth.dll ( using MS VisualStudio 2010 ) ... (1) I compiled your code into SubAuth.dll ( using MS VisualStudio 2010 ) ... BUT - NO c:\SubAuth.log and NO C:\testlog.txt file ( as per MSDN code WriteLog .... ) ... BUT - NO c:\SubAuth.log and NO C:\testlog.txt file ( as per MSDN code WriteLog .... ) ... were you successful in creating the subauth.log or .txt files ? were you successful in creating the subauth.log or .txt files ? 这篇关于如何将额外的参数传递给Windows Server 2k8R2 \ 2K3上的SubAuthentication DLL(代码C ++)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!推荐答案
(2) I copied SubAuth.dll into c:\windows\system32 on a test domain controller ...
(3) I edited registry - HKLM\System\CurrentControlSet\Control\Lsa\Kerberos\Auth0 (REG_SZ) = 'subauth' ( without ' ) ...
(4) made logon from a domain workstation ...
(2) I copied SubAuth.dll into c:\windows\system32 on a test domain controller ...
(3) I edited registry - HKLM\System\CurrentControlSet\Control\Lsa\Kerberos\Auth0 (REG_SZ) = 'subauth' ( without ' ) ...
(4) made logon from a domain workstation ...