734 lines
17 KiB
C
734 lines
17 KiB
C
/*++
|
||
|
||
Copyright (c) 2000 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
lsa.c
|
||
|
||
Abstract:
|
||
|
||
Implements security network logon
|
||
|
||
Author:
|
||
|
||
Ahmed Mohamed (ahmedm) 1-Feb-2000
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
#include <nt.h>
|
||
#include <ntdef.h>
|
||
#include <ntrtl.h>
|
||
#include <nturtl.h>
|
||
|
||
#include <ntlsa.h>
|
||
#include <ntmsv1_0.h>
|
||
|
||
#include <windows.h>
|
||
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <stdarg.h>
|
||
#include <string.h>
|
||
#include <fcntl.h>
|
||
#include <io.h>
|
||
|
||
//int lstrlenW(char *);
|
||
|
||
typedef int BOOL;
|
||
typedef unsigned int UINT;
|
||
typedef unsigned int *PUINT;
|
||
typedef unsigned char *LPBYTE;
|
||
|
||
|
||
#define LocalLSAInit() (LsaHandle != NULL)
|
||
|
||
#ifdef LSA_AUDIT_FLAG
|
||
int LsaAuditFlag = 0;
|
||
#endif
|
||
|
||
#define BUF_SIZ 512
|
||
|
||
|
||
void
|
||
replstar(
|
||
IN char * starred,
|
||
OUT LPWSTR UnicodeOut
|
||
)
|
||
/*++ replstar
|
||
|
||
Routine Description:
|
||
|
||
replaces the '*' in the string with either spaces or NULL
|
||
if it's the only memeber of the string. Used by parse().
|
||
|
||
Converts the resultant string to unicode.
|
||
|
||
Arguments:
|
||
|
||
char * starred -
|
||
|
||
Return Value:
|
||
|
||
void -
|
||
Warnings:
|
||
--*/
|
||
{
|
||
char *cp;
|
||
STRING AnsiString;
|
||
UNICODE_STRING UnicodeString;
|
||
|
||
if ( !strcmp(starred,"*") ) {
|
||
*starred = '\0';
|
||
} else {
|
||
for ( cp = starred; *cp; ++cp )
|
||
if (*cp == '*')
|
||
*cp = ' ';
|
||
}
|
||
|
||
//
|
||
// Convert the result to unicode
|
||
//
|
||
|
||
AnsiString.Buffer = starred;
|
||
AnsiString.Length = AnsiString.MaximumLength =
|
||
(USHORT) strlen( starred );
|
||
|
||
UnicodeString.Buffer = UnicodeOut;
|
||
UnicodeString.Length = 0;
|
||
UnicodeString.MaximumLength = BUF_SIZ * sizeof(WCHAR);
|
||
|
||
(VOID) RtlAnsiStringToUnicodeString( &UnicodeString, &AnsiString, FALSE );
|
||
return;
|
||
}
|
||
|
||
VOID
|
||
NlpPutString(
|
||
IN PUNICODE_STRING OutString,
|
||
IN PUNICODE_STRING InString,
|
||
IN PUCHAR *Where
|
||
)
|
||
/*++ NlpPutString
|
||
|
||
Routine Description:
|
||
|
||
This routine copies the InString string to the memory pointed to by
|
||
the Where parameter, and fixes the OutString string to point to that
|
||
new copy.
|
||
|
||
Parameters:
|
||
|
||
OutString - A pointer to a destination NT string
|
||
|
||
InString - A pointer to an NT string to be copied
|
||
|
||
Where - A pointer to space to put the actual string for the
|
||
OutString. The pointer is adjusted to point to the first byte
|
||
following the copied string.
|
||
|
||
Return Values:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
ASSERT( OutString != NULL );
|
||
ASSERT( InString != NULL );
|
||
ASSERT( Where != NULL && *Where != NULL);
|
||
|
||
if ( InString->Length > 0 )
|
||
{
|
||
|
||
OutString->Buffer = (PWCH) *Where;
|
||
OutString->MaximumLength = InString->Length;
|
||
*Where += OutString->MaximumLength;
|
||
|
||
RtlCopyString( (PSTRING) OutString, (PSTRING) InString );
|
||
|
||
}
|
||
else
|
||
{
|
||
RtlInitUnicodeString(OutString, NULL);
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
|
||
BOOL
|
||
LsapLogonNetwork(
|
||
IN HANDLE LsaHandle,
|
||
IN ULONG AuthenticationPackage,
|
||
IN LPWSTR Username,
|
||
IN PUCHAR ChallengeToClient,
|
||
IN PMSV1_0_GETCHALLENRESP_RESPONSE ChallengeResponse,
|
||
IN UINT cbChallengeResponse,
|
||
IN LPWSTR Domain,
|
||
OUT PLUID LogonId,
|
||
OUT PHANDLE TokenHandle
|
||
)
|
||
/*++ LogonNetwork
|
||
|
||
Routine Description:
|
||
|
||
Logs a user onto the network
|
||
|
||
Arguments:
|
||
IN LPWSTR Username - self explanatory
|
||
IN ChallengeToClient - The challenge sent to the client
|
||
IN ChallengeResponse - The response sent from the client
|
||
IN LPWSTR Domain - Logon Domain Name
|
||
OUT PLUID LogonId - Unique generated logon id
|
||
OUT PHANDLE TokenHandle - handle to the logon token
|
||
|
||
Return Value:
|
||
|
||
BOOL -
|
||
|
||
Warnings:
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS Status;
|
||
UNICODE_STRING TempString;
|
||
UNICODE_STRING TempString2;
|
||
UNICODE_STRING OriginName;
|
||
PMSV1_0_LM20_LOGON Auth;
|
||
PCHAR Auth1[MSV1_0_CHALLENGE_LENGTH + BUF_SIZ*2];
|
||
PUCHAR Strings;
|
||
PMSV1_0_LM20_LOGON_PROFILE ProfileBuffer;
|
||
ULONG ProfileBufferSize;
|
||
NTSTATUS SubStatus;
|
||
TOKEN_SOURCE SourceContext;
|
||
QUOTA_LIMITS QuotaLimits;
|
||
|
||
|
||
/*
|
||
* Fill in the Authentication structure.
|
||
*/
|
||
Auth = (PMSV1_0_LM20_LOGON) Auth1;
|
||
|
||
Strings = (PUCHAR)(Auth + 1);
|
||
|
||
Auth->MessageType = MsV1_0Lm20Logon;
|
||
RtlMoveMemory( Auth->ChallengeToClient,
|
||
ChallengeToClient,
|
||
MSV1_0_CHALLENGE_LENGTH );
|
||
|
||
/* Init Strings
|
||
* username
|
||
*/
|
||
RtlInitUnicodeString( &TempString, Username );
|
||
NlpPutString( &Auth->UserName, &TempString, &Strings );
|
||
|
||
/*
|
||
* workstation name
|
||
*/
|
||
RtlInitUnicodeString( &TempString, L"NetQFS" );
|
||
NlpPutString( &Auth->Workstation, &TempString, &Strings );
|
||
|
||
/*
|
||
* Challenge Response
|
||
*/
|
||
|
||
Auth->CaseSensitiveChallengeResponse.Length = 0;
|
||
Auth->CaseSensitiveChallengeResponse.MaximumLength = 0;
|
||
Auth->CaseSensitiveChallengeResponse.Buffer = NULL;
|
||
|
||
|
||
#ifdef OLD
|
||
RtlInitUnicodeString(
|
||
(PUNICODE_STRING)&TempString2,
|
||
(PCWSTR)ChallengeResponse );
|
||
#else
|
||
TempString2.Buffer = (PWSTR)ChallengeResponse;
|
||
TempString2.Length = (USHORT)cbChallengeResponse;
|
||
TempString2.MaximumLength = TempString2.Length;
|
||
#endif
|
||
if( TempString2.Length > 24 ) {
|
||
TempString2.Length = 24;
|
||
}
|
||
NlpPutString(
|
||
(PUNICODE_STRING)&Auth->CaseInsensitiveChallengeResponse,
|
||
(PUNICODE_STRING)&TempString2,
|
||
&Strings );
|
||
/*
|
||
* domain
|
||
*/
|
||
RtlInitUnicodeString( &TempString, Domain );
|
||
NlpPutString( &Auth->LogonDomainName, &TempString, &Strings );
|
||
|
||
|
||
RtlInitUnicodeString( &OriginName, L"NetQFS" );
|
||
Status = LsaLogonUser(
|
||
LsaHandle,
|
||
(PSTRING)&OriginName,
|
||
Network,
|
||
AuthenticationPackage,
|
||
// LATER? AuthenticationPackage | LSA_CALL_LICENSE_SERVER,
|
||
Auth,
|
||
(ULONG)(Strings - (PUCHAR)Auth),
|
||
NULL,
|
||
&SourceContext,
|
||
(PVOID *)&ProfileBuffer,
|
||
&ProfileBufferSize,
|
||
LogonId,
|
||
TokenHandle,
|
||
&QuotaLimits,
|
||
&SubStatus );
|
||
|
||
if ( !NT_SUCCESS( Status ) )
|
||
{
|
||
extern void WINAPI debug_log(char *,...);
|
||
|
||
debug_log("Logon failed %x\n",Status);
|
||
// LSA Can't be trusted to not scrog our variables
|
||
*TokenHandle = NULL;
|
||
return( FALSE );
|
||
}
|
||
LsaFreeReturnBuffer( ProfileBuffer );
|
||
|
||
return( TRUE );
|
||
}
|
||
|
||
BOOL
|
||
LsapChallenge(
|
||
HANDLE LsaHandle,
|
||
ULONG AuthenticationPackage,
|
||
UCHAR *ChallengeToClient
|
||
)
|
||
/*++ Challenge
|
||
|
||
Routine Description:
|
||
|
||
get a challenge
|
||
|
||
Arguments:
|
||
OUT ChallengeToClient - Returns the challenge to send to the client
|
||
|
||
Return Value:
|
||
NTSTATUS -
|
||
Warnings:
|
||
--*/
|
||
{
|
||
NTSTATUS Status;
|
||
NTSTATUS ProtocolStatus;
|
||
ULONG ResponseSize;
|
||
MSV1_0_LM20_CHALLENGE_REQUEST Request;
|
||
PMSV1_0_LM20_CHALLENGE_RESPONSE Response;
|
||
|
||
/*
|
||
* Fill in the Authentication structure.
|
||
*/
|
||
|
||
Request.MessageType = MsV1_0Lm20ChallengeRequest;
|
||
|
||
Status = LsaCallAuthenticationPackage (
|
||
LsaHandle,
|
||
AuthenticationPackage,
|
||
&Request,
|
||
sizeof(Request),
|
||
(PVOID *)&Response,
|
||
&ResponseSize,
|
||
&ProtocolStatus );
|
||
|
||
if ( !NT_SUCCESS( Status ) || !NT_SUCCESS( ProtocolStatus) )
|
||
{
|
||
printf("ChallengeRequest failed %x\n",Status);
|
||
return( FALSE );
|
||
}
|
||
|
||
RtlMoveMemory( ChallengeToClient,
|
||
Response->ChallengeToClient,
|
||
MSV1_0_CHALLENGE_LENGTH );
|
||
|
||
LsaFreeReturnBuffer( Response );
|
||
|
||
return( TRUE );
|
||
}
|
||
|
||
|
||
BOOL
|
||
LsaGetChallenge(
|
||
HANDLE LsaHandle,
|
||
ULONG AuthenticationPackage,
|
||
LPBYTE lpChallenge,
|
||
UINT cbSize,
|
||
PUINT lpcbChallengeSize
|
||
)
|
||
{
|
||
#ifdef LSA_AUDIT_FLAG
|
||
if (LsaAuditFlag == TRUE) {
|
||
memset(lpChallenge, 0, MSV1_0_CHALLENGE_LENGTH);
|
||
*lpcbChallengeSize = MSV1_0_CHALLENGE_LENGTH;
|
||
return TRUE;
|
||
}
|
||
#endif
|
||
|
||
if( LocalLSAInit() ) {
|
||
*lpcbChallengeSize = MSV1_0_CHALLENGE_LENGTH;
|
||
return LsapChallenge( LsaHandle, AuthenticationPackage, lpChallenge );
|
||
} else {
|
||
return( FALSE );
|
||
}
|
||
}
|
||
|
||
BOOL
|
||
LsaValidateLogon(
|
||
HANDLE LsaHandle,
|
||
ULONG AuthenticationPackage,
|
||
LPBYTE lpChallenge,
|
||
UINT cbChallengeSize,
|
||
LPBYTE lpResponse,
|
||
UINT cbResponseSize,
|
||
LPSTR lpszUserName,
|
||
LPSTR lpszDomainName,
|
||
LUID *pLogonId,
|
||
PHANDLE phLogonToken
|
||
)
|
||
{
|
||
WCHAR wcUser[ BUF_SIZ ];
|
||
WCHAR wcDomain[ BUF_SIZ ];
|
||
BOOL nlRet;
|
||
DWORD sz = BUF_SIZ;
|
||
|
||
#ifdef LSA_AUDIT_FLAG
|
||
if (LsaAuditFlag == 1) {
|
||
pLogonId->LowPart = 10;
|
||
pLogonId->HighPart = 0;
|
||
*phLogonToken = INVALID_HANDLE_VALUE;
|
||
return TRUE;
|
||
}
|
||
#endif
|
||
|
||
if (GetUserName((LPSTR)wcUser, &sz)) {
|
||
if (lpszUserName != NULL && *lpszUserName != '\0' &&
|
||
_stricmp(lpszUserName, (LPSTR)wcUser) &&
|
||
_stricmp(lpszUserName, "administrator")) {
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
if( !LocalLSAInit() ) {
|
||
return( FALSE );
|
||
}
|
||
replstar( lpszUserName, wcUser );
|
||
replstar( lpszDomainName, wcDomain );
|
||
nlRet = LsapLogonNetwork( LsaHandle, AuthenticationPackage,
|
||
wcUser, lpChallenge,
|
||
(PMSV1_0_GETCHALLENRESP_RESPONSE)lpResponse,
|
||
cbResponseSize, wcDomain, pLogonId, phLogonToken );
|
||
return( nlRet );
|
||
}
|
||
|
||
BOOL
|
||
LsaGetChallengeResponse(
|
||
HANDLE LsaHandle,
|
||
ULONG AuthenticationPackage,
|
||
LUID LogonId,
|
||
LPSTR lpszPasswordK1,
|
||
int cbPasswordK1,
|
||
LPSTR lpszChallenge,
|
||
int cbChallenge,
|
||
int *pcbPasswordK1,
|
||
BOOL *pbHasPasswordK1 )
|
||
{
|
||
NTSTATUS Status;
|
||
NTSTATUS ProtocolStatus;
|
||
ULONG ResponseSize;
|
||
PMSV1_0_GETCHALLENRESP_RESPONSE Response;
|
||
PMSV1_0_GETCHALLENRESP_REQUEST Request;
|
||
|
||
PCHAR Auth1[BUF_SIZ];
|
||
PUCHAR Strings;
|
||
|
||
|
||
if( !LocalLSAInit() ) {
|
||
*pbHasPasswordK1 = FALSE;
|
||
return( FALSE );
|
||
}
|
||
Request = (PMSV1_0_GETCHALLENRESP_REQUEST) Auth1;
|
||
Request->MessageType = MsV1_0Lm20GetChallengeResponse;
|
||
Request->ParameterControl = 0;
|
||
Request->ParameterControl |= USE_PRIMARY_PASSWORD;
|
||
Request->LogonId = LogonId;
|
||
Strings = (PUCHAR)(Request + 1);
|
||
RtlMoveMemory( Request->ChallengeToClient,
|
||
lpszChallenge,
|
||
cbChallenge );
|
||
|
||
RtlInitUnicodeString( &Request->Password, NULL );
|
||
Status = LsaCallAuthenticationPackage (
|
||
LsaHandle,
|
||
AuthenticationPackage,
|
||
Request,
|
||
sizeof(MSV1_0_GETCHALLENRESP_REQUEST),
|
||
(PVOID *)&Response,
|
||
&ResponseSize,
|
||
&ProtocolStatus );
|
||
if ( !NT_SUCCESS( Status ) || !NT_SUCCESS( ProtocolStatus) )
|
||
{
|
||
return( FALSE );
|
||
}
|
||
|
||
*pcbPasswordK1 = (Response)->CaseInsensitiveChallengeResponse.Length;
|
||
memcpy( lpszPasswordK1,
|
||
(Response)->CaseInsensitiveChallengeResponse.Buffer,
|
||
(Response)->CaseInsensitiveChallengeResponse.Length );
|
||
*pbHasPasswordK1 = TRUE;
|
||
|
||
LsaFreeReturnBuffer( Response );
|
||
|
||
return( TRUE );
|
||
}
|
||
|
||
#ifdef QON_TCB_REQUIRED
|
||
// When we have support for untrusted on REQUEST we disable this. Till then we need TCB.
|
||
// I am disabling this since the we don't need TCB anymore. Note if we
|
||
// want to run in win2k then we must have TCB and this code path reenabled.
|
||
|
||
NTSTATUS
|
||
LsaInit(HANDLE *pLsaHandle, ULONG *pAuthenticationPackage)
|
||
{
|
||
char MyName[MAX_PATH];
|
||
char * ModuleName;
|
||
STRING LogonProcessName;
|
||
STRING PackageName;
|
||
ULONG dummy;
|
||
NTSTATUS Status;
|
||
NTSTATUS TempStatus;
|
||
BOOLEAN WasEnabled;
|
||
HANDLE LsaHandle = NULL;
|
||
ULONG AuthenticationPackage;
|
||
|
||
BOOLEAN fThread = FALSE; // did we enable privilege in thread token?
|
||
BOOL fReverted = FALSE; // did we RevertToSelf() during call?
|
||
HANDLE hPreviousToken = NULL;
|
||
|
||
#ifdef LSA_AUDIT_FLAG
|
||
if (LsaAuditFlag == TRUE) {
|
||
*pLsaHandle = 0;
|
||
*pAuthenticationPackage = 0;
|
||
return STATUS_SUCCESS;
|
||
}
|
||
#endif
|
||
|
||
//
|
||
// three SeTcbPrivilege scenarios:
|
||
// 1. present in process token, thread not impersonating.
|
||
// 2. present in process token, thread is impersonating.
|
||
// 3. present in thread token.
|
||
//
|
||
|
||
//
|
||
// try in this order:
|
||
// process token (original method).
|
||
// if thread impersonating, thread token
|
||
// if thread impersonating, process token after reverting.
|
||
//
|
||
|
||
Status = RtlAdjustPrivilege(SE_TCB_PRIVILEGE, TRUE, FALSE, &WasEnabled);
|
||
|
||
if (!NT_SUCCESS(Status))
|
||
{
|
||
TempStatus = NtOpenThreadToken(
|
||
NtCurrentThread(),
|
||
TOKEN_IMPERSONATE,
|
||
FALSE,
|
||
&hPreviousToken
|
||
);
|
||
|
||
if( !NT_SUCCESS(TempStatus) ) {
|
||
|
||
//
|
||
// retry with accesscheck against process.
|
||
//
|
||
|
||
if( TempStatus != STATUS_ACCESS_DENIED )
|
||
goto Cleanup;
|
||
|
||
TempStatus = NtOpenThreadToken(
|
||
NtCurrentThread(),
|
||
TOKEN_IMPERSONATE,
|
||
TRUE,
|
||
&hPreviousToken
|
||
);
|
||
|
||
if( !NT_SUCCESS(TempStatus) )
|
||
goto Cleanup;
|
||
}
|
||
|
||
//
|
||
// thread token is present.
|
||
// first, try enabling the privilege in the thread token.
|
||
//
|
||
|
||
fThread = TRUE;
|
||
|
||
Status = RtlAdjustPrivilege(SE_TCB_PRIVILEGE, TRUE, fThread, &WasEnabled);
|
||
|
||
if( !NT_SUCCESS(Status) ) {
|
||
|
||
HANDLE NewToken = NULL;
|
||
|
||
//
|
||
// if that fails, try reverting and enabling privilege in process token.
|
||
//
|
||
|
||
TempStatus = NtSetInformationThread(
|
||
NtCurrentThread(),
|
||
ThreadImpersonationToken,
|
||
&NewToken,
|
||
sizeof(NewToken)
|
||
);
|
||
|
||
if( !NT_SUCCESS(TempStatus) )
|
||
goto Cleanup;
|
||
|
||
fThread = FALSE;
|
||
fReverted = TRUE;
|
||
|
||
Status = RtlAdjustPrivilege(SE_TCB_PRIVILEGE, TRUE, fThread, &WasEnabled);
|
||
if( !NT_SUCCESS(Status) )
|
||
goto Cleanup;
|
||
}
|
||
}
|
||
|
||
GetModuleFileNameA(NULL, MyName, MAX_PATH);
|
||
ModuleName = strrchr(MyName, '\\');
|
||
if (!ModuleName)
|
||
{
|
||
ModuleName = MyName;
|
||
}
|
||
|
||
|
||
//
|
||
// Hookup to the LSA and locate our authentication package.
|
||
//
|
||
|
||
RtlInitString(&LogonProcessName, ModuleName);
|
||
|
||
Status = LsaRegisterLogonProcess(
|
||
&LogonProcessName,
|
||
&LsaHandle,
|
||
&dummy
|
||
);
|
||
|
||
|
||
//
|
||
// Turn off the privilege now.
|
||
//
|
||
|
||
if( !WasEnabled ) {
|
||
|
||
(VOID) RtlAdjustPrivilege(SE_TCB_PRIVILEGE, FALSE, fThread, &WasEnabled);
|
||
}
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
LsaHandle = NULL;
|
||
goto Cleanup;
|
||
}
|
||
|
||
|
||
//
|
||
// Connect with the MSV1_0 authentication package
|
||
//
|
||
RtlInitString(&PackageName, MSV1_0_PACKAGE_NAME); //"MICROSOFT_AUTHENTICATION_PACKAGE_V1_0");
|
||
Status = LsaLookupAuthenticationPackage (
|
||
LsaHandle,
|
||
&PackageName,
|
||
&AuthenticationPackage
|
||
);
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
goto Cleanup;
|
||
}
|
||
|
||
*pLsaHandle = LsaHandle;
|
||
*pAuthenticationPackage = AuthenticationPackage;
|
||
|
||
Cleanup:
|
||
|
||
if( hPreviousToken ) {
|
||
|
||
if( fReverted ) {
|
||
|
||
//
|
||
// put old token back...
|
||
//
|
||
|
||
(VOID) NtSetInformationThread(
|
||
NtCurrentThread(),
|
||
ThreadImpersonationToken,
|
||
&hPreviousToken,
|
||
sizeof(hPreviousToken)
|
||
);
|
||
}
|
||
|
||
NtClose( hPreviousToken );
|
||
}
|
||
|
||
|
||
if( !NT_SUCCESS(Status) ) {
|
||
|
||
if( LsaHandle ) {
|
||
(VOID) LsaDeregisterLogonProcess( LsaHandle );
|
||
LsaHandle = NULL;
|
||
}
|
||
|
||
}
|
||
|
||
return Status;
|
||
}
|
||
|
||
#else
|
||
|
||
NTSTATUS
|
||
LsaInit(HANDLE *pLsaHandle, ULONG *pAuthenticationPackage)
|
||
{
|
||
char MyName[MAX_PATH];
|
||
char * ModuleName;
|
||
STRING LogonProcessName;
|
||
STRING PackageName;
|
||
ULONG dummy;
|
||
NTSTATUS Status;
|
||
NTSTATUS TempStatus;
|
||
BOOLEAN WasEnabled;
|
||
HANDLE LsaHandle;
|
||
ULONG AuthenticationPackage;
|
||
|
||
BOOLEAN fThread = FALSE; // did we enable privilege in thread token?
|
||
BOOL fReverted = FALSE; // did we RevertToSelf() during call?
|
||
HANDLE hPreviousToken = NULL;
|
||
|
||
//
|
||
// Connect with LSA process
|
||
//
|
||
Status = LsaConnectUntrusted(&LsaHandle);
|
||
if (!NT_SUCCESS(Status))
|
||
return Status;
|
||
|
||
//
|
||
// Connect with the MSV1_0 authentication package
|
||
//
|
||
RtlInitString(&PackageName, MSV1_0_PACKAGE_NAME); //"MICROSOFT_AUTHENTICATION_PACKAGE_V1_0");
|
||
Status = LsaLookupAuthenticationPackage (
|
||
LsaHandle,
|
||
&PackageName,
|
||
&AuthenticationPackage
|
||
);
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
*pLsaHandle = LsaHandle;
|
||
*pAuthenticationPackage = AuthenticationPackage;
|
||
} else {
|
||
(VOID) LsaDeregisterLogonProcess( LsaHandle );
|
||
}
|
||
|
||
return Status;
|
||
}
|
||
#endif
|
||
|