⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 msvsam.c

📁 安全支持提供器接口(SSPI)源码
💻 C
📖 第 1 页 / 共 5 页
字号:
            *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 + -