public static PasswordPolicyContext createLdapPasswordPolicyConfiguration(
        final LdapPasswordPolicyProperties passwordPolicy,
        final Authenticator authenticator,
        final Multimap<String, Object> attributes) {
        val passwordPolicyContext = new PasswordPolicyContext(passwordPolicy);
        val requestHandlers = new HashSet<AuthenticationRequestHandler>();
        val responseHandlers = new HashSet<AuthenticationResponseHandler>();

        val customPolicyClass = passwordPolicy.getCustomPolicyClass();
        if (StringUtils.isNotBlank(customPolicyClass)) {
            try {
                LOGGER.debug("Configuration indicates use of a custom password policy handler [{}]", customPolicyClass);
                val clazz = (Class<AuthenticationResponseHandler>) Class.forName(customPolicyClass);
                responseHandlers.add(clazz.getDeclaredConstructor().newInstance());
            } catch (final Exception e) {
                LoggingUtils.warn(LOGGER, "Unable to construct an instance of the password policy handler", e);
            }
        }
        LOGGER.debug("Password policy authentication response handler is set to accommodate directory type: [{}]", passwordPolicy.getType());
        switch (passwordPolicy.getType()) {
            case AD -> {
                val warningPeriod = Period.ofDays(passwordPolicyContext.getPasswordWarningNumberOfDays());
                val handler = FunctionUtils.doIf(passwordPolicy.getPasswordExpirationNumberOfDays() > 0,
                        () -> {
                            val expirationPeriod = Period.ofDays(passwordPolicy.getPasswordExpirationNumberOfDays());
                            LOGGER.debug("Creating active directory authentication response handler with expiration period [{}] and warning period [{}]", expirationPeriod, warningPeriod);
                            return new ActiveDirectoryAuthenticationResponseHandler(expirationPeriod, warningPeriod);
                        },
                        () -> {
                            LOGGER.debug("Creating active directory authentication response handler with warning period [{}]", warningPeriod);
                            return new ActiveDirectoryAuthenticationResponseHandler(warningPeriod);
                        })
                    .get();
                responseHandlers.add(handler);
                Arrays.stream(ActiveDirectoryAuthenticationResponseHandler.ATTRIBUTES).forEach(attr -> {
                    LOGGER.debug("Configuring authentication to retrieve password policy attribute [{}]", attr);
                    attributes.put(attr, attr);
                });
            }
            case FreeIPA -> {
                Arrays.stream(FreeIPAAuthenticationResponseHandler.ATTRIBUTES).forEach(attr -> {
                    LOGGER.debug("Configuring authentication to retrieve password policy attribute [{}]", attr);
                    attributes.put(attr, attr);
                });
                responseHandlers.add(new FreeIPAAuthenticationResponseHandler(
                    Period.ofDays(passwordPolicyContext.getPasswordWarningNumberOfDays()), passwordPolicyContext.getLoginFailures()));
            }
            case EDirectory -> {
                Arrays.stream(EDirectoryAuthenticationResponseHandler.ATTRIBUTES).forEach(attr -> {
                    LOGGER.debug("Configuring authentication to retrieve password policy attribute [{}]", attr);
                    attributes.put(attr, attr);
                });
                responseHandlers.add(new EDirectoryAuthenticationResponseHandler(Period.ofDays(passwordPolicyContext.getPasswordWarningNumberOfDays())));
            }
            default -> {
                requestHandlers.add(new PasswordPolicyAuthenticationRequestHandler());
                responseHandlers.add(new PasswordPolicyAuthenticationResponseHandler());
                responseHandlers.add(new PasswordExpirationAuthenticationResponseHandler());
            }
        }
        if (!requestHandlers.isEmpty()) {
            authenticator.setRequestHandlers(requestHandlers.toArray(AuthenticationRequestHandler[]::new));
        }
        authenticator.setResponseHandlers(responseHandlers.toArray(AuthenticationResponseHandler[]::new));

        LOGGER.debug("LDAP authentication response handlers configured are: [{}]", responseHandlers);

        if (!passwordPolicy.isAccountStateHandlingEnabled()) {
            passwordPolicyContext.setAccountStateHandler((response, configuration) -> new ArrayList<>());
            LOGGER.trace("Handling LDAP account states is disabled via CAS configuration");
        } else if (StringUtils.isNotBlank(passwordPolicy.getWarningAttributeName()) && StringUtils.isNotBlank(passwordPolicy.getWarningAttributeValue())) {
            val accountHandler = new OptionalWarningLdapAccountStateHandler();
            accountHandler.setDisplayWarningOnMatch(passwordPolicy.isDisplayWarningOnMatch());
            accountHandler.setWarnAttributeName(passwordPolicy.getWarningAttributeName());
            accountHandler.setWarningAttributeValue(passwordPolicy.getWarningAttributeValue());
            accountHandler.setAttributesToErrorMap(passwordPolicy.getPolicyAttributes());
            passwordPolicyContext.setAccountStateHandler(accountHandler);
            LOGGER.debug("Configuring an warning account state handler for LDAP authentication for warning attribute [{}] and value [{}]",
                passwordPolicy.getWarningAttributeName(), passwordPolicy.getWarningAttributeValue());
        } else {
            val accountHandler = new DefaultLdapAccountStateHandler();
            accountHandler.setAttributesToErrorMap(passwordPolicy.getPolicyAttributes());
            passwordPolicyContext.setAccountStateHandler(accountHandler);
            LOGGER.debug("Configuring the default account state handler for LDAP authentication");
        }
        return passwordPolicyContext;
    }
Create ldap password policy configuration.

@param passwordPolicy the password policy
@param authenticator  the authenticator
@param attributes     the attributes
@return the password policy context
support/cas-server-support-ldap-core/src/main/java/org/apereo/cas/util/LdapUtils.java