📄 nlmain.c
字号:
//
// Map the user's logon domain against the current mapping
// in the registry.
//
Status = NlpMapLogonDomain(
&LogonDomainName,
&PrimaryCredential->LogonDomainName
);
if (!NT_SUCCESS(Status)) {
goto Cleanup;
}
#else
LogonDomainName = PrimaryCredential->LogonDomainName;
#endif
}
} else if ( Status == STATUS_NO_SUCH_LOGON_SESSION ||
Status == STATUS_UNSUCCESSFUL ) {
//
// Clean up the status code
//
Status = STATUS_NO_SUCH_LOGON_SESSION;
//
// If the caller wants at least the password from the primary
// credential, just use a NULL session primary credential.
//
if ( (GetRespRequest->ParameterControl & USE_PRIMARY_PASSWORD ) ==
USE_PRIMARY_PASSWORD ) {
PrimaryCredential = NULL;
//
// If part of the information was supplied by the caller,
// report the error to the caller.
//
} else {
KdPrint(("MSV1_0: MspLm20GetChallengeResponse: cannot "
" GetPrimaryCredential %lx\n", Status ));
goto Cleanup;
}
} else {
KdPrint(("MSV1_0: MspLm20GetChallengeResponse: cannot "
" GetPrimaryCredential %lx\n", Status ));
goto Cleanup;
}
Credential = PrimaryCredential;
}
//
// If the caller passed in a password to use,
// use it to build a credential.
//
if ( (GetRespRequest->ParameterControl & USE_PRIMARY_PASSWORD) == 0 ) {
NlpPutOwfsInPrimaryCredential( &GetRespRequest->Password,
&BuiltCredential );
//
// Use the newly allocated credential to get the password information
// from.
//
Credential = &BuiltCredential;
}
//
// Build the appropriate response.
//
if ( Credential != NULL ) {
//
// If the DC is asserted to have been upgraded, we should use NTLM3
// if caller supplies the NTLM3 parameters
//
if ((NtLmProtocolSupported >= UseNtlm3) &&
(GetRespRequest->ParameterControl & GCR_NTLM3_PARMS)
) {
USHORT Ntlm3ResponseSize;
UNICODE_STRING Ntlm3UserName;
UNICODE_STRING Ntlm3LogonDomainName;
UNICODE_STRING Ntlm3ServerName;
// use the server name supplied by the caller
Ntlm3ServerName = GetRespRequest->ServerName;
// even if user name and domain are supplied, use current logged
// in user if so requested
if (GetRespRequest->ParameterControl & USE_PRIMARY_PASSWORD) {
Ntlm3UserName = Credential->UserName;
Ntlm3LogonDomainName = Credential->LogonDomainName;
} else {
Ntlm3UserName = GetRespRequest->UserName;
Ntlm3LogonDomainName = GetRespRequest->LogonDomainName;
}
//
// Allocate the response
//
Ntlm3ResponseSize =
sizeof(MSV1_0_NTLM3_RESPONSE) + Ntlm3ServerName.Length;
pNtlm3Response = (*Lsa.AllocateLsaHeap)( Ntlm3ResponseSize );
if ( pNtlm3Response == NULL ) {
KdPrint(("MSV1_0: MspLm20GetChallengeResponse: No memory %ld\n",
Ntlm3ResponseSize ));
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Cleanup;
}
MsvpLm20GetNtlm3ChallengeResponse(
&Credential->NtOwfPassword,
&Ntlm3UserName,
&Ntlm3LogonDomainName,
&Ntlm3ServerName,
GetRespRequest->ChallengeToClient,
pNtlm3Response, // BUGBUG??
(PMSV1_0_LM3_RESPONSE)&LmResponse,
&UserSessionKey,
(PLM_SESSION_KEY)LanmanSessionKey
);
NtResponseString.Buffer = (PUCHAR) pNtlm3Response;
NtResponseString.Length = Ntlm3ResponseSize;
LmResponseString.Buffer = (PUCHAR) &LmResponse;
LmResponseString.Length = sizeof(LmResponse);
} else {
//
// if requested, generate our own challenge, and mix it with that
// of the server's
//
if (GetRespRequest->ParameterControl & GENERATE_CLIENT_CHALLENGE) {
SspGenerateRandomBits(ChallengeFromClient, MSV1_0_CHALLENGE_LENGTH);
#ifdef USE_CONSTANT_CHALLENGE
RtlZeroMemory(ChallengeFromClient, MSV1_0_CHALLENGE_LENGTH);
#endif
RtlCopyMemory(
ChallengeToClient,
GetRespRequest->ChallengeToClient,
MSV1_0_CHALLENGE_LENGTH
);
MsvpCalculateNtlm2Challenge (
GetRespRequest->ChallengeToClient,
ChallengeFromClient,
GetRespRequest->ChallengeToClient
);
}
Status = RtlCalculateNtResponse(
(PNT_CHALLENGE) GetRespRequest->ChallengeToClient,
&Credential->NtOwfPassword,
&NtResponse );
if ( !NT_SUCCESS( Status ) ) {
goto Cleanup;
}
//
// send the client challenge back in the LM response slot if we made one
//
if (GetRespRequest->ParameterControl & GENERATE_CLIENT_CHALLENGE) {
RtlZeroMemory(
&LmResponse,
sizeof(LmResponse)
);
RtlCopyMemory(
&LmResponse,
ChallengeFromClient,
MSV1_0_CHALLENGE_LENGTH
);
//
// Return the LM response if policy set that way for backwards compatibility.
//
} else if ((NtLmProtocolSupported <= AllowLm) ) {
Status = RtlCalculateLmResponse(
(PLM_CHALLENGE) GetRespRequest->ChallengeToClient,
&Credential->LmOwfPassword,
&LmResponse );
if ( !NT_SUCCESS( Status ) ) {
goto Cleanup;
}
//
//
// Can't return LM response -- so use NT response
// (to allow LM_KEY generatation)
//
} else {
RtlCopyMemory(
&LmResponse,
&NtResponse,
sizeof(LmResponse)
);
}
NtResponseString.Buffer = (PUCHAR) &NtResponse;
NtResponseString.Length = sizeof(NtResponse);
LmResponseString.Buffer = (PUCHAR) &LmResponse;
LmResponseString.Length = sizeof(LmResponse);
//
// Compute the session keys
//
if (GetRespRequest->ParameterControl & GENERATE_CLIENT_CHALLENGE) {
//
// assert: we're talking to an NT4-SP4 or later server
// and the user's DC hasn't been upgraded to NTLM++
// generate session key from MD4(NT hash) -
// aka NtUserSessionKey - that is different for each session
//
Status = RtlCalculateUserSessionKeyNt(
&NtResponse,
&Credential->NtOwfPassword,
&UserSessionKey );
if ( !NT_SUCCESS( Status ) ) {
goto Cleanup;
}
MsvpCalculateNtlm2SessionKeys(
&UserSessionKey,
ChallengeToClient,
ChallengeFromClient,
(PUSER_SESSION_KEY)&UserSessionKey,
(PLM_SESSION_KEY)LanmanSessionKey
);
} else if ( GetRespRequest->ParameterControl & RETURN_NON_NT_USER_SESSION_KEY){
//
// If the redir didn't negotiate an NT protocol with the server,
// use the lanman session key.
//
if ( Credential->LmPasswordPresent ) {
ASSERT( sizeof(UserSessionKey) >= sizeof(LanmanSessionKey) );
RtlCopyMemory( &UserSessionKey,
&Credential->LmOwfPassword,
sizeof(LanmanSessionKey) );
}
} else {
if ( !Credential->NtPasswordPresent ) {
RtlCopyMemory( &Credential->NtOwfPassword,
&NlpNullNtOwfPassword,
sizeof(Credential->NtOwfPassword) );
}
Status = RtlCalculateUserSessionKeyNt(
&NtResponse,
&Credential->NtOwfPassword,
&UserSessionKey );
if ( !NT_SUCCESS( Status ) ) {
goto Cleanup;
}
}
if ( Credential->LmPasswordPresent ) {
RtlCopyMemory( LanmanSessionKey,
&Credential->LmOwfPassword,
sizeof(LanmanSessionKey) );
}
} // UseNtlm3
}
//
// Allocate a buffer to return to the caller.
//
*ReturnBufferSize = sizeof(MSV1_0_GETCHALLENRESP_RESPONSE) +
LogonDomainName.Length + sizeof(WCHAR) +
UserName.Length + sizeof(WCHAR) +
NtResponseString.Length + sizeof(WCHAR) +
LmResponseString.Length + sizeof(WCHAR);
Status = NlpAllocateClientBuffer( &ClientBufferDesc,
sizeof(MSV1_0_GETCHALLENRESP_RESPONSE),
*ReturnBufferSize );
if ( !NT_SUCCESS( Status ) ) {
goto Cleanup;
}
GetRespResponse = (PMSV1_0_GETCHALLENRESP_RESPONSE) ClientBufferDesc.MsvBuffer;
//
// Fill in the return buffer.
//
GetRespResponse->MessageType = MsV1_0Lm20GetChallengeResponse;
RtlCopyMemory( GetRespResponse->UserSessionKey,
&UserSessionKey,
sizeof(UserSessionKey));
RtlCopyMemory( GetRespResponse->LanmanSessionKey,
LanmanSessionKey,
sizeof(LanmanSessionKey) );
//
// Copy the logon domain name (the string may be empty)
//
NlpPutClientString( &ClientBufferDesc,
&GetRespResponse->LogonDomainName,
&LogonDomainName );
//
// Copy the user name (the string may be empty)
//
NlpPutClientString( &ClientBufferDesc,
&GetRespResponse->UserName,
&UserName );
//
// Copy the Challenge Responses to the client buffer.
//
NlpPutClientString(
&ClientBufferDesc,
(PUNICODE_STRING)
&GetRespResponse->CaseSensitiveChallengeResponse,
(PUNICODE_STRING) &NtResponseString );
NlpPutClientString(
&ClientBufferDesc,
(PUNICODE_STRING)
&GetRespResponse->CaseInsensitiveChallengeResponse,
(PUNICODE_STRING)&LmResponseString );
//
// Flush the buffer to the client's address space.
//
Status = NlpFlushClientBuffer( &ClientBufferDesc,
ProtocolReturnBuffer );
Cleanup:
//
// If we weren't successful, free the buffer in the clients address space.
//
if ( !NT_SUCCESS(Status) ) {
NlpFreeClientBuffer( &ClientBufferDesc );
}
//
// Cleanup locally used resources
//
if ( PrimaryCredential != NULL ) {
(*Lsa.FreeLsaHeap)( PrimaryCredential );
}
#ifndef DONT_MAP_DOMAIN_ON_REQUEST
if (LogonDomainName.Buffer != NULL) {
NtLmFree(LogonDomainName.Buffer);
}
#endif
if ( pNtlm3Response != NULL ) {
(*Lsa.FreeLsaHeap)( pNtlm3Response );
}
//
// Return status to the caller.
//
*ProtocolStatus = Status;
return STATUS_SUCCESS;
}
NTSTATUS
MspLm20EnumUsers (
IN PLSA_CLIENT_REQUEST ClientRequest,
IN PVOID ProtocolSubmitBuffer,
IN PVOID ClientBufferBase,
IN ULONG SubmitBufferSize,
OUT PVOID *ProtocolReturnBuffer,
OUT PULONG ReturnBufferSize,
OUT PNTSTATUS ProtocolStatus
)
/*++
Routine Description:
This routine is the dispatch routine for LsaCallAuthenticationPackage()
with a message type of MsV1_0Lm20EnumerateUsers. This routine
enumerates all of the interactive, service, and batch logons to the MSV1_0
authentication package.
Arguments:
The arguments to this routine are identical to those of LsaApCallPackage.
Only the special attributes of these parameters as they apply to
this routine are mentioned here.
Return Value:
STATUS_SUCCESS - Indicates the service completed successfully.
--*/
{
NTSTATUS Status;
PMSV1_0_ENUMUSERS_REQUEST EnumRequest;
PMSV1_0_ENUMUSERS_RESPONSE EnumResponse;
CLIENT_BUFFER_DESC ClientBufferDesc;
ULONG LogonCount = 0;
PACTIVE_LOGON Logon;
BOOLEAN ActiveLogonsAreLocked = FALSE;
PUCHAR Where;
//
// Ensure the specified Submit Buffer is of reasonable size and
// relocate all of the pointers to be relative to the LSA allocated
// buffer.
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -