📄 msvsam.c
字号:
if ( RtlCompareMemory(
LogonNetworkInfo->
NtChallengeResponse.Buffer,
&NtResponse,
LogonNetworkInfo->NtChallengeResponse.Length ) ==
NT_RESPONSE_LENGTH ) {
AlreadyValidated = TRUE;
} else if ( RtlCompareMemory(
LogonNetworkInfo->
LmChallengeResponse.Buffer,
&NtResponse,
LogonNetworkInfo->LmChallengeResponse.Length ) ==
NT_RESPONSE_LENGTH ) {
AlreadyValidated = TRUE;
}
}
}
// if we're requiring all Win9x clients to have been upgraded, fail out now
if (!AlreadyValidated && NtLmProtocolSupported >= RefuseLm)
return FALSE;
//
// if the LM response is the right size
// validate against the LM version of the response
// this applies also when both NTOWF and LMOWF are not present in SAM.
//
if (!AlreadyValidated &&
( LogonNetworkInfo->LmChallengeResponse.Length == LM_RESPONSE_LENGTH ) &&
( (Passwords->LmPasswordPresent) || (!Passwords->LmPasswordPresent && !Passwords->NtPasswordPresent) ) &&
( LogonNetworkInfo->NtChallengeResponse.Length < NT_RESPONSE_LENGTH )
) {
LM_RESPONSE LmResponse;
//
// Compute what the response should be.
//
Status = RtlCalculateLmResponse(
&LogonNetworkInfo->LmChallenge,
&Passwords->LmOwfPassword,
&LmResponse );
if ( NT_SUCCESS(Status) ) {
//
// If the responses match, the passwords are valid.
//
if ( RtlCompareMemory(
LogonNetworkInfo->
LmChallengeResponse.Buffer,
&LmResponse,
LM_RESPONSE_LENGTH ) ==
LM_RESPONSE_LENGTH ) {
AlreadyValidated = TRUE;
*UserFlags |= LOGON_USED_LM_PASSWORD;
}
}
}
//
// If we haven't already validated this user,
// Validate a Cleartext password on a Network logon request.
//
if ( !AlreadyValidated ) {
// If Cleartext passwords are not allowed,
// indicate the password doesn't match.
//
if((LogonInfo->ParameterControl & CLEARTEXT_PASSWORD_ALLOWED) == 0){
return FALSE;
}
//
// Compute the OWF password for the specified Cleartext password and
// compare that to the OWF password retrieved from SAM.
//
//
// If we're in UasCompatibilityMode,
// and we don't have the NT password in SAM or
// we don't have the NT password supplied by the caller.
// validate against the LM version of the password.
//
// if neither password are present, we validate against
// the empty computed LMOWF.
//
if ( UasCompatibilityRequired &&
((Passwords->LmPasswordPresent) || (!Passwords->LmPasswordPresent && !Passwords->NtPasswordPresent)) &&
(!Passwords->NtPasswordPresent ||
LogonNetworkInfo->NtChallengeResponse.Length == 0 ) ) {
LM_OWF_PASSWORD LmOwfPassword;
CHAR LmPassword[LM20_PWLEN+1];
USHORT i;
//
// Compute the LmOwfPassword for the cleartext password passed in.
// (Enforce length restrictions on LanMan compatible passwords.)
//
if ( LogonNetworkInfo->LmChallengeResponse.Length >
sizeof(LmPassword) ) {
return FALSE;
}
RtlZeroMemory( &LmPassword, sizeof(LmPassword) );
for (i = 0; i < LogonNetworkInfo->LmChallengeResponse.Length; i++) {
LmPassword[i] =
RtlUpperChar(LogonNetworkInfo->LmChallengeResponse.Buffer[i]);
}
(VOID) RtlCalculateLmOwfPassword( LmPassword, &LmOwfPassword );
if ( RtlCompareMemory( &Passwords->LmOwfPassword,
&LmOwfPassword,
LM_OWF_PASSWORD_LENGTH ) !=
LM_OWF_PASSWORD_LENGTH ) {
//
// Try the case preserved clear text password, too.
// (I know of no client that does this,
// but it is compatible with the LM 2.x server.)
//
RtlZeroMemory( &LmPassword, sizeof(LmPassword) );
RtlCopyMemory(
&LmPassword,
LogonNetworkInfo->LmChallengeResponse.Buffer,
LogonNetworkInfo->LmChallengeResponse.Length);
(VOID) RtlCalculateLmOwfPassword( LmPassword,
&LmOwfPassword );
if ( RtlCompareMemory( &Passwords->LmOwfPassword,
&LmOwfPassword,
LM_OWF_PASSWORD_LENGTH ) !=
LM_OWF_PASSWORD_LENGTH ) {
return FALSE;
}
}
*UserFlags |= LOGON_USED_LM_PASSWORD;
//
// In all other circumstances, use the NT version of the password.
// This enforces case sensitivity.
//
} else {
NT_OWF_PASSWORD NtOwfPassword;
//
// Compute the NtOwfPassword for the cleartext password passed in.
//
Status = RtlCalculateNtOwfPassword(
(PUNICODE_STRING)
&LogonNetworkInfo->NtChallengeResponse,
&NtOwfPassword );
if ( RtlCompareMemory( &Passwords->NtOwfPassword,
&NtOwfPassword,
NT_OWF_PASSWORD_LENGTH ) !=
NT_OWF_PASSWORD_LENGTH ) {
return FALSE;
}
}
*UserFlags |= LOGON_NOENCRYPTION;
}
//
// ASSERT: the network logon has been authenticated
//
// Compute the session keys.
//
// If the client negotiated a non-NT protocol,
// use the lanman session key as the UserSessionKey.
//
if ( LogonNetworkInfo->NtChallengeResponse.Length == 0 ) {
ASSERT( sizeof(*UserSessionKey) >= sizeof(*LmSessionKey) );
RtlCopyMemory( UserSessionKey,
&Passwords->LmOwfPassword,
sizeof(*LmSessionKey) );
} else {
//
// Return the NT UserSessionKey unless this is an account
// that doesn't have the NT version of the password.
// (A null password counts as a password).
//
if ( Passwords->NtPasswordPresent || !Passwords->LmPasswordPresent){
Status = RtlCalculateUserSessionKeyNt(
(PNT_RESPONSE) NULL, // Argument not used
&Passwords->NtOwfPassword,
UserSessionKey );
ASSERT( NT_SUCCESS(Status) );
}
}
//
// Return the LM SessionKey unless this is an account
// that doesn't have the LM version of the password.
// (A null password counts as a password).
//
if ( Passwords->LmPasswordPresent || !Passwords->NtPasswordPresent ) {
RtlCopyMemory( LmSessionKey,
&Passwords->LmOwfPassword,
sizeof(*LmSessionKey) );
}
break;
//
// Any other LogonLevel is an internal error.
//
default:
return FALSE;
}
return TRUE;
}
BOOLEAN
MsvpEqualSidPrefix(
IN PSID DomainSid,
IN PSID GroupSid
)
/*++
Routine Description:
This routine checks to see if the specified group sid came from the
specified domain by verifying that the domain portion of the group sid
is equal to the domain sid.
Arguments:
DomainSid - Sid of the domain for comparison.
GroupSid - Sid of the group for comparison
Returns:
TRUE - The group sid came from the specified domain.
FALSE - The group sid did not come from the specified domain.
--*/
{
PISID LocalGroupSid = (PISID) GroupSid;
PISID LocalDomainSid = (PISID) DomainSid;
if ((LocalGroupSid->SubAuthorityCount == LocalDomainSid->SubAuthorityCount + 1) &&
RtlEqualMemory(
RtlIdentifierAuthoritySid(LocalDomainSid),
RtlIdentifierAuthoritySid(LocalGroupSid),
RtlLengthRequiredSid(
LocalDomainSid->SubAuthorityCount
) - FIELD_OFFSET(SID,IdentifierAuthority)
)) {
return(TRUE);
}
return(FALSE);
}
NTSTATUS
MsvpFilterGroupMembership(
IN PSID_AND_ATTRIBUTES_LIST CompleteMembership,
IN PSID LogonDomainId,
OUT PSAMPR_GET_GROUPS_BUFFER LocalMembership,
OUT PSID_AND_ATTRIBUTES_LIST GlobalMembership,
OUT PULONG GlobalMembershipSize
)
/*++
Routine Description:
This routine separates the complete transitive group membership into
portions from this domain and portions from others.
Arguments:
CompleteMembership - The complete transitive membership.
LogonDomainId - SID of the logon domain, used for compressing group
membership.
LocalMembership - Receives a list of rids corresponding to groups in this
domain. The list should be freed with MIDL_user_free.
GlobalMembership - Recevies a list of sids corresponding to groups in
other domain. The list, but not the sids, should be free with
MIDL_user_free.
GlobalMembershipSize - Size, in bytes, of the sids in the global membership
and the size of the SID_AND_ATTRIBUTES structures.
Returns:
STATUS_SUCCESS on success
STATUS_INSUFFICIENT_RESOURCES on for memory allocation failures.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
ULONG LocalCount = 0;
ULONG GlobalCount = 0;
ULONG GlobalSize = 0;
ULONG Index;
LocalMembership->MembershipCount = 0;
LocalMembership->Groups = NULL;
GlobalMembership->Count = 0;
GlobalMembership->SidAndAttributes = NULL;
//
// Define a flag so we don't have to do the comparison twice.
//
#define MSVP_LOCAL_GROUP_ATTR 0x20000000
for (Index = 0; Index < CompleteMembership->Count ; Index++ ) {
ASSERT((CompleteMembership->SidAndAttributes[Index].Attributes & MSVP_LOCAL_GROUP_ATTR) == 0);
if (MsvpEqualSidPrefix(
LogonDomainId,
CompleteMembership->SidAndAttributes[Index].Sid
)) {
CompleteMembership->SidAndAttributes[Index].Attributes |= MSVP_LOCAL_GROUP_ATTR;
LocalCount++;
} else {
GlobalCount++;
GlobalSize += sizeof(SID_AND_ATTRIBUTES) + RtlLengthSid(CompleteMembership->SidAndAttributes[Index].Sid);
}
}
//
// Allocate the arrays for the output
//
if (LocalCount != 0)
{
LocalMembership->Groups = (PGROUP_MEMBERSHIP) MIDL_user_allocate(LocalCount * sizeof(GROUP_MEMBERSHIP));
if (LocalMembership->Groups == NULL) {
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Cleanup;
}
LocalMembership->MembershipCount = LocalCount;
}
if (GlobalCount != 0)
{
GlobalMembership->SidAndAttributes = (PSID_AND_ATTRIBUTES) MIDL_user_allocate(GlobalCount * sizeof(SID_AND_ATTRIBUTES));
if (GlobalMembership->SidAndAttributes == NULL) {
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Cleanup;
}
GlobalMembership->Count = GlobalCount;
}
//
// Loop through again copy the rid or sid into the respective array
//
LocalCount = 0;
GlobalCount = 0;
for (Index = 0; Index < CompleteMembership->Count ; Index++ ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -