📄 msvsam.c
字号:
*Authoritative = TRUE;
goto Cleanup;
}
//
// If there is a SubAuthentication package zero, call it
//
if (NlpSubAuthZeroExists) {
ULONG LocalUserFlags = 0;
ULONG Flags = 0;
if ( SecureChannelType != MsvApSecureChannel ) {
Flags |= MSV1_0_PASSTHRU;
}
if ( GuestRelativeId != 0 ) {
Flags |= MSV1_0_GUEST_LOGON;
}
Status = Msv1_0SubAuthenticationRoutineZero(
LogonLevel,
LogonInformation,
Flags,
(PUSER_ALL_INFORMATION) UserAll,
&WhichFields,
&LocalUserFlags,
Authoritative,
&LogoffTime,
&KickoffTime );
if ( !NT_SUCCESS(Status) ) {
goto Cleanup;
}
//
// Sanity check what the SubAuthentication package returned
//
if ( (WhichFields & ~USER_ALL_PARAMETERS) != 0 ) {
Status = STATUS_INTERNAL_ERROR;
*Authoritative = TRUE;
goto Cleanup;
}
UserFlags |= LocalUserFlags;
}
}
//
// If the account is a machine account,
// let the caller know he got the password right.
// (But don't let him actually log on).
//
// But, for NT 5.0, we must allow accounts with account control
// USER_WORKSTATION_TRUST_ACCOUNT for remote boot clients who
// will logon with their machine accounts
if ( (UserAll->UserAccountControl & USER_MACHINE_ACCOUNT_MASK) != 0 ) {
if (UserAll->UserAccountControl & USER_INTERDOMAIN_TRUST_ACCOUNT) {
Status = STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT;
} else if (UserAll->UserAccountControl &
USER_WORKSTATION_TRUST_ACCOUNT) {
if ( (LogonInfo->ParameterControl & MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT) == 0) {
Status = STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT;
} else {
UNICODE_STRING MachineAccountName;
NTSTATUS TempStatus;
//
// if the password was correct, and it happened to match
// the machine name, dis-allow it regardless.
//
//
// Compute the lower case user name.
//
TempStatus = RtlDowncaseUnicodeString( &MachineAccountName,
(PUNICODE_STRING)&UserAll->UserName,
TRUE );
if( NT_SUCCESS( TempStatus ) )
{
USHORT LastChar = MachineAccountName.Length / sizeof(WCHAR);
if( LastChar )
{
if( MachineAccountName.Buffer[LastChar-1] == L'$' )
{
MachineAccountName.Length -= sizeof(WCHAR);
}
if( LastChar > LM20_PWLEN )
{
MachineAccountName.Length = LM20_PWLEN * sizeof(WCHAR);
}
}
if ( UserAll->NtPasswordPresent ) {
NT_OWF_PASSWORD NtOwfMachineName;
NT_OWF_PASSWORD *pOwf;
pOwf = ((PNT_OWF_PASSWORD)(UserAll->NtOwfPassword.Buffer));
RtlCalculateNtOwfPassword(
&MachineAccountName,
&NtOwfMachineName );
if ( RtlCompareMemory( pOwf,
&NtOwfMachineName,
NT_OWF_PASSWORD_LENGTH ) ==
NT_OWF_PASSWORD_LENGTH ) {
Status = STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT;
}
}
RtlFreeUnicodeString( &MachineAccountName );
}
}
} else if (UserAll->UserAccountControl & USER_SERVER_TRUST_ACCOUNT) {
if ( (LogonInfo->ParameterControl & MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT) == 0) {
Status = STATUS_NOLOGON_SERVER_TRUST_ACCOUNT;
} else {
//
// it's a server trust account.
// treat same way as workstation trust account.
UNICODE_STRING MachineAccountName;
NTSTATUS TempStatus;
// NOTE: some code here is duplicated from above.
// this will be merged when a new Rtl has been added for
// computing initial machine password from machine acct name.
//
//
// if the password was correct, and it happened to match
// the machine name, dis-allow it regardless.
//
//
// Compute the lower case user name.
//
TempStatus = RtlDowncaseUnicodeString( &MachineAccountName,
(PUNICODE_STRING)&UserAll->UserName,
TRUE );
if( NT_SUCCESS( TempStatus ) )
{
USHORT LastChar = MachineAccountName.Length / sizeof(WCHAR);
if( LastChar )
{
if( MachineAccountName.Buffer[LastChar-1] == L'$' )
{
MachineAccountName.Length -= sizeof(WCHAR);
}
if( LastChar > LM20_PWLEN )
{
MachineAccountName.Length = LM20_PWLEN * sizeof(WCHAR);
}
}
if ( UserAll->NtPasswordPresent ) {
NT_OWF_PASSWORD NtOwfMachineName;
NT_OWF_PASSWORD *pOwf;
pOwf = ((PNT_OWF_PASSWORD)(UserAll->NtOwfPassword.Buffer));
RtlCalculateNtOwfPassword(
&MachineAccountName,
&NtOwfMachineName );
if ( RtlCompareMemory( pOwf,
&NtOwfMachineName,
NT_OWF_PASSWORD_LENGTH ) ==
NT_OWF_PASSWORD_LENGTH ) {
Status = STATUS_NOLOGON_SERVER_TRUST_ACCOUNT;
}
}
RtlFreeUnicodeString( &MachineAccountName );
}
//
// Let the client know that this was
// a server trust account
//
UserFlags |= LOGON_SERVER_TRUST_ACCOUNT;
}
} else {
Status = STATUS_NO_SUCH_USER;
}
if (!NT_SUCCESS(Status)) {
*Authoritative = TRUE;
goto Cleanup;
}
}
//
// Filter the groups into global groups (from other domains) and local
// groups (from this domain).
//
Status = MsvpFilterGroupMembership(
&GroupMembership,
LogonDomainId,
&GroupsBuffer,
&GlobalGroupMembership,
&GlobalMembershipSize
);
if ( !NT_SUCCESS(Status) ) {
*Authoritative = FALSE;
goto Cleanup;
}
Cleanup:
if (NT_SUCCESS(Status) || fSubAuthEx)
{
//
// Allocate a return buffer for validation information.
// (Return less information for a network logon)
// (Return UserParameters for a MNS logon)
//
ValidationSamSize = sizeof( NETLOGON_VALIDATION_SAM_INFO2 ) +
GroupsBuffer.MembershipCount * sizeof(GROUP_MEMBERSHIP) +
LogonDomainName->Length + sizeof(WCHAR) +
LogonServer->Length + sizeof(WCHAR) +
RtlLengthSid( LogonDomainId );
if ( LogonLevel != NetlogonNetworkInformation ) {
ValidationSamSize +=
UserAll->UserName.Length + sizeof(WCHAR) +
UserAll->FullName.Length + sizeof(WCHAR) +
UserAll->ScriptPath.Length + sizeof(WCHAR)+
UserAll->ProfilePath.Length + sizeof(WCHAR) +
UserAll->HomeDirectory.Length + sizeof(WCHAR) +
UserAll->HomeDirectoryDrive.Length + sizeof(WCHAR);
}
//
// for network logon of the guest account, return the account
// name so the correct name ends up in the session list.
//
if ( LogonLevel == NetlogonNetworkInformation &&
GuestRelativeId != 0 ) {
ValidationSamSize +=
UserAll->UserName.Length + sizeof(WCHAR) ;
}
if ( LogonInfo->ParameterControl & MSV1_0_RETURN_USER_PARAMETERS ) {
ValidationSamSize +=
UserAll->Parameters.Length + sizeof(WCHAR);
} else if ( LogonInfo->ParameterControl & MSV1_0_RETURN_PROFILE_PATH ) {
ValidationSamSize +=
UserAll->ProfilePath.Length + sizeof(WCHAR);
}
//
// If the caller can handle extra groups, let them have the groups from
// other domains.
//
if (ValidationLevel == NetlogonValidationSamInfo2) {
ValidationSamSize += GlobalMembershipSize;
}
ValidationSamSize = ROUND_UP_COUNT( ValidationSamSize, sizeof(WCHAR) );
ValidationSam = MIDL_user_allocate( ValidationSamSize );
if ( ValidationSam == NULL ) {
*Authoritative = FALSE;
fSubAuthEx = FALSE; // avoid nasty loop condition
Status = STATUS_NO_MEMORY;
goto Cleanup;
}
//
// Default unused fields (and ExpansionRoom) to zero.
//
RtlZeroMemory( ValidationSam, ValidationSamSize );
//
// Copy the scalars to the validation buffer.
//
Where = (PUCHAR) (ValidationSam + 1);
if ((SubAuthValidationInformation.WhichFields & MSV1_0_VALIDATION_LOGOFF_TIME) != 0) {
NEW_TO_OLD_LARGE_INTEGER( SubAuthValidationInformation.LogoffTime, ValidationSam->LogoffTime );
}
else {
NEW_TO_OLD_LARGE_INTEGER( LogoffTime, ValidationSam->LogoffTime );
}
if ((SubAuthValidationInformation.WhichFields & MSV1_0_VALIDATION_KICKOFF_TIME) != 0) {
NEW_TO_OLD_LARGE_INTEGER( SubAuthValidationInformation.KickoffTime, ValidationSam->KickOffTime );
}
else {
NEW_TO_OLD_LARGE_INTEGER( KickoffTime, ValidationSam->KickOffTime );
}
if ((SubAuthValidationInformation.WhichFields & MSV1_0_VALIDATION_SESSION_KEY) != 0) {
ValidationSam->UserSessionKey = SubAuthValidationInformation.SessionKey;
}
else {
ValidationSam->UserSessionKey = UserSessionKey;
}
if ((SubAuthValidationInformation.WhichFields & MSV1_0_VALIDATION_USER_FLAGS) != 0) {
ValidationSam->UserFlags = SubAuthValidationInformation.UserFlags;
}
else {
ValidationSam->UserFlags = UserFlags;
}
if ((SubAuthValidationInformation.WhichFields & MSV1_0_VALIDATION_USER_ID) != 0) {
ValidationSam->UserId = SubAuthValidationInformation.UserId;
}
else {
ValidationSam->UserId = UserAll->UserId;
}
ValidationSam->LogonTime = UserAll->LastLogon;
ValidationSam->PasswordLastSet = UserAll->PasswordLastSet;
ValidationSam->PasswordCanChange = UserAll->PasswordCanChange;
ValidationSam->PasswordMustChange = UserAll->PasswordMustChange;
ValidationSam->LogonCount = UserAll->LogonCount;
ValidationSam->BadPasswordCount = UserAll->BadPasswordCount;
ValidationSam->PrimaryGroupId = UserAll->PrimaryGroupId;
ValidationSam->GroupCount = GroupsBuffer.MembershipCount;
ASSERT( SAMINFO_LM_SESSION_KEY_SIZE == sizeof(LmSessionKey) );
RtlCopyMemory( &ValidationSam->ExpansionRoom[SAMINFO_LM_SESSION_KEY],
&LmSessionKey,
SAMINFO_LM_SESSION_KEY_SIZE );
ValidationSam->ExpansionRoom[SAMINFO_USER_ACCOUNT_CONTROL] = UserAll->UserAccountControl;
// Save any status for subuath users not returned by the subauth package
if (fSubAuthEx)
{
ValidationSam->ExpansionRoom[SAMINFO_SUBAUTH_STATUS] = Status;
}
//
// Copy ULONG aligned data to the validation buffer.
//
RtlCopyMemory(
Where,
GroupsBuffer.Groups,
GroupsBuffer.MembershipCount * sizeof(GROUP_MEMBERSHIP) );
ValidationSam->GroupIds = (PGROUP_MEMBERSHIP) Where;
Where += GroupsBuffer.MembershipCount * sizeof(GROUP_MEMBERSHIP);
RtlCopyMemory(
Where,
LogonDomainId,
RtlLengthSid( LogonDomainId
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -