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

📄 msvsam.c

📁 安全支持提供器接口(SSPI)源码
💻 C
📖 第 1 页 / 共 5 页
字号:


    //
    // Open the user account.
    //

    Status = I_SamIGetUserLogonInformation(
                DomainHandle,
                SamFlags,
                &LocalUserName,
                &UserAllInfo,
                &GroupMembership,
                &UserHandle
                );


    if ( !NT_SUCCESS(Status) ) {
        UserHandle = NULL;
        *Authoritative = FALSE;
        Status = STATUS_NO_SUCH_USER;
        goto Cleanup;
    }



    UserAll = &UserAllInfo->All;

    //
    // pickup RelativeId from looked up information.
    //

    RelativeId = UserAll->UserId;

    //
    // If the account type isn't allowed,
    //  Treat this as though the User Account doesn't exist.
    //
    // SubAuthentication packages can be more specific than this test but
    // they can't become less restrictive.
    //

    if ( (UserAccountControl & UserAll->UserAccountControl) == 0 ) {
        *Authoritative = FALSE;
        Status = STATUS_NO_SUCH_USER;
        goto Cleanup;
    }

    //
    // determine if machine account, if so, certain failures are treated
    // as Authoritative, to prevent fallback to guest and returning incorrect
    // error codes.
    //

    if ( (UserAll->UserAccountControl & USER_MACHINE_ACCOUNT_MASK) != 0 ) {
        fMachineAccount = TRUE;
    } else {
        fMachineAccount = FALSE;
    }


    //
    // If there is a SubAuthentication DLL,
    //  call it to do all the authentication work.
    //

    if ( (LogonInfo->ParameterControl & MSV1_0_SUBAUTHENTICATION_DLL) &&
         (!(LogonInfo->ParameterControl & MSV1_0_SUBAUTHENTICATION_DLL_EX))) {

        ULONG LocalUserFlags = 0;
        ULONG Flags = 0;

        //
        // Ensure the account isn't locked out.
        // We did this regardless before NT 5.0. Now, we do it when either
        // No SubAuth package is specified or
        // New SubAuth package asks us to do account lockout test
        // But, for those who call with old SubAuth packages, they will expect
        // us to do the dirty work.
        //

        if (RelativeId != DOMAIN_USER_RID_ADMIN) {
            if ( UserAll->UserAccountControl & USER_ACCOUNT_AUTO_LOCKED ) {

                //
                // Since the UI strongly encourages admins to disable user
                // accounts rather than delete them.  Treat disabled acccount as
                // non-authoritative allowing the search to continue for other
                // accounts by the same name.
                //

                if ( UserAll->UserAccountControl & USER_ACCOUNT_DISABLED ) {
                    *Authoritative = fMachineAccount;
                } else {
                    *Authoritative = TRUE;
                }

                Status = STATUS_ACCOUNT_LOCKED_OUT;
                goto Cleanup;

            }
        }

        if ( SecureChannelType != MsvApSecureChannel ) {
            Flags |= MSV1_0_PASSTHRU;
        }
        if ( GuestRelativeId != 0 ) {
            Flags |= MSV1_0_GUEST_LOGON;
        }

        Status = Msv1_0SubAuthenticationRoutine(
                    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;



    } else { // we may still have an NT 5.0 SubAuth dll

        //
        // If there is an NT 5.0 SubAuthentication DLL,
        // call it to do all the authentication work.
        //

        if ( (LogonInfo->ParameterControl & MSV1_0_SUBAUTHENTICATION_DLL_EX))
        {
            ULONG LocalUserFlags = 0;
            ULONG Flags = 0;

            if ( SecureChannelType != MsvApSecureChannel ) {
                Flags |= MSV1_0_PASSTHRU;
            }
            if ( GuestRelativeId != 0 ) {
                Flags |= MSV1_0_GUEST_LOGON;
            }

            Status = Msv1_0SubAuthenticationRoutineEx(
                        LogonLevel,
                        LogonInformation,
                        Flags,
                        (PUSER_ALL_INFORMATION) UserAll,
                        (SAM_HANDLE)UserHandle,
                        &SubAuthValidationInformation,
                        &ActionsPerformed );

            *Authoritative = SubAuthValidationInformation.Authoritative;

            if ( !NT_SUCCESS(Status) ) {
                goto Cleanup;
            }

            // We need to do this because even if any of the following checks
            // fail, ARAP stills wants the returned blobs from teh subauth
            // package to be returned to the caller.

            fSubAuthEx = TRUE;

        }

        //
        // Ensure the account isn't locked out.
        //

        if ((ActionsPerformed & MSV1_0_SUBAUTH_LOCKOUT) == 0)
        {
            if (RelativeId != DOMAIN_USER_RID_ADMIN) {
                if ( UserAll->UserAccountControl & USER_ACCOUNT_AUTO_LOCKED ) {

                     //
                     // Since the UI strongly encourages admins to disable user
                     // accounts rather than delete them.  Treat disabled acccount as
                     // non-authoritative allowing the search to continue for other
                     // accounts by the same name.
                     //

                     if ( UserAll->UserAccountControl & USER_ACCOUNT_DISABLED ) {
                         *Authoritative = fMachineAccount;
                     } else {
                         *Authoritative = TRUE;
                     }

                    Status = STATUS_ACCOUNT_LOCKED_OUT;
                    goto Cleanup;
                }
            }
        }

        //
        // Check the password if there's no subauth or if subauth did
        // not already check password.
        //

        if ((ActionsPerformed & MSV1_0_SUBAUTH_PASSWORD) == 0)
        {
            if ( SecureChannelType != NullSecureChannel ) {
                USER_INTERNAL1_INFORMATION Passwords;

                //
                // Copy the password info to the right structure.
                //

                Passwords.NtPasswordPresent = UserAll->NtPasswordPresent;
                if ( UserAll->NtPasswordPresent ) {
                    Passwords.NtOwfPassword =
                        *((PNT_OWF_PASSWORD)(UserAll->NtOwfPassword.Buffer));
                }

                Passwords.LmPasswordPresent = UserAll->LmPasswordPresent;
                if ( UserAll->LmPasswordPresent ) {
                    Passwords.LmOwfPassword =
                        *((PLM_OWF_PASSWORD)(UserAll->LmOwfPassword.Buffer));
                }


                //
                // If the password specified doesn't match the SAM password,
                //    then we've got a password mismatch.
                //

                if ( ! MsvpPasswordValidate (
                            UasCompatibilityRequired,
                            LogonLevel,
                            LogonInformation,
                            &Passwords,
                            &UserFlags,
                            &UserSessionKey,
                            &LmSessionKey ) ) {

                    //
                    // If this is a guest logon and the guest account has no password,
                    //  let the user log on.
                    //
                    // This special case check is after the MsvpPasswordValidate to
                    // give MsvpPasswordValidate every opportunity to compute the
                    // correct values for UserSessionKey and LmSessionKey.
                    //

                    if ( GuestRelativeId != 0 &&
                         !UserAll->NtPasswordPresent &&
                         !UserAll->LmPasswordPresent ) {

                        RtlZeroMemory( &UserSessionKey, sizeof(UserSessionKey) );
                        RtlZeroMemory( &LmSessionKey, sizeof(LmSessionKey) );


                    //
                    // The password mismatched.  We treat STATUS_WRONG_PASSWORD as
                    // an authoritative response.  Our caller may choose to do otherwise.
                    //

                    } else {

                        Status = STATUS_WRONG_PASSWORD;

                        //
                        // Since the UI strongly encourages admins to disable user
                        // accounts rather than delete them.  Treat disabled acccount as
                        // non-authoritative allowing the search to continue for other
                        // accounts by the same name.
                        //
                        if ( UserAll->UserAccountControl & USER_ACCOUNT_DISABLED ) {
                            *Authoritative = fMachineAccount;
                        } else {
                            *Authoritative = TRUE;
                        }

                        goto Cleanup;
                    }
                }
            }
        }

        //
        // Prevent some things from effecting the Administrator user
        //

        if (RelativeId != DOMAIN_USER_RID_ADMIN) {

            //
            // Check if the account is disabled if there's no subauth or if
            // subauth has not already checked.
            //


            if ((ActionsPerformed & MSV1_0_SUBAUTH_ACCOUNT_DISABLED) == 0)
            {
                if ( UserAll->UserAccountControl & USER_ACCOUNT_DISABLED ) {
                    //
                    // Since the UI strongly encourages admins to disable user
                    // accounts rather than delete them.  Treat disabled acccount as
                    // non-authoritative allowing the search to continue for other
                    // accounts by the same name.
                    //

                    *Authoritative = fMachineAccount;
                    Status = STATUS_ACCOUNT_DISABLED;
                    goto Cleanup;
                }
            }

            //
            // Check if the account has expired if there's no subauth or if
            // subauth has not already checked.
            //

            if ((ActionsPerformed & MSV1_0_SUBAUTH_ACCOUNT_EXPIRY) == 0)
            {
                OLD_TO_NEW_LARGE_INTEGER( UserAll->AccountExpires, AccountExpires );

                if ( AccountExpires.QuadPart != 0 &&
                    LogonTime.QuadPart >= AccountExpires.QuadPart ) {
                    *Authoritative = TRUE;
                    Status = STATUS_ACCOUNT_EXPIRED;
                    goto Cleanup;
                }
            }


            //
            // The password is valid, check to see if the password is expired.
            //  (SAM will have appropriately set PasswordMustChange to reflect
            //  USER_DONT_EXPIRE_PASSWORD)
            //
            // Don't check if the password is expired if we didn't check the password.
            // BUGBUG What happens when a Subauth does the password checking
            // but requests us to do password expiry ??
            //

            if ((ActionsPerformed & MSV1_0_SUBAUTH_PASSWORD_EXPIRY) == 0)
            {

              OLD_TO_NEW_LARGE_INTEGER( UserAll->PasswordMustChange, PasswordMustChange );
              OLD_TO_NEW_LARGE_INTEGER( UserAll->PasswordLastSet, PasswordLastSet );

              if ( SecureChannelType != NullSecureChannel ) {
                if ( LogonTime.QuadPart >= PasswordMustChange.QuadPart ) {

                    if ( PasswordLastSet.QuadPart == 0 ) {
                        Status = STATUS_PASSWORD_MUST_CHANGE;
                    } else {
                        Status = STATUS_PASSWORD_EXPIRED;
                    }
                    *Authoritative = TRUE;
                    goto Cleanup;
                }
              }
            }
        }

        //
        // Validate the workstation the user logged on from.
        //
        // Ditch leading \\ on workstation name before passing it to SAM.
        //

        LocalWorkstation = LogonInfo->Workstation;
        if ( LocalWorkstation.Length > 0 &&
             LocalWorkstation.Buffer[0] == L'\\' &&
             LocalWorkstation.Buffer[1] == L'\\' ) {
            LocalWorkstation.Buffer += 2;
            LocalWorkstation.Length -= 2*sizeof(WCHAR);
            LocalWorkstation.MaximumLength -= 2*sizeof(WCHAR);
        }


        //
        // Check if SAM found some more specific reason to not allow logon.
        //

        Status = I_SamIAccountRestrictions(
                    UserHandle,
                    &LocalWorkstation,
                    (PUNICODE_STRING) &UserAll->WorkStations,
                    (PLOGON_HOURS) &UserAll->LogonHours,
                    &LogoffTime,
                    &KickoffTime );

        if ( !NT_SUCCESS(Status) ) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -