package org.apereo.cas.authentication.surrogate; import org.apereo.cas.authentication.principal.Principal; import org.apereo.cas.configuration.model.support.surrogate.SurrogateAuthenticationProperties; import org.apereo.cas.configuration.support.Beans; import org.apereo.cas.util.LdapUtils; import org.apereo.cas.util.RegexUtils; import org.ldaptive.ConnectionFactory; import org.ldaptive.LdapAttribute; import org.ldaptive.LdapEntry; import org.ldaptive.Response; import org.ldaptive.SearchFilter; import org.ldaptive.SearchResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Arrays; import java.util.Collection; import java.util.LinkedHashSet; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; /** * This is {@link LdapSurrogateUsernamePasswordService}. * * @author Misagh Moayyed * @since 5.1.0 */ public class LdapSurrogateUsernamePasswordService implements SurrogateAuthenticationService { private static final Logger LOGGER = LoggerFactory.getLogger(LdapSurrogateUsernamePasswordService.class); private final ConnectionFactory connectionFactory; private final SurrogateAuthenticationProperties.Ldap ldapProperties; public LdapSurrogateUsernamePasswordService(final ConnectionFactory connectionFactory, final SurrogateAuthenticationProperties.Ldap ldap) { this.connectionFactory = connectionFactory; this.ldapProperties = ldap; } @Override public boolean canAuthenticateAs(final String username, final Principal surrogate) { try { if (username.equalsIgnoreCase(surrogate.getId())) { return true; } final SearchFilter filter = Beans.newLdaptiveSearchFilter(ldapProperties.getSurrogateSearchFilter(), Arrays.asList(username)); LOGGER.debug("Using search filter: [{}]", filter); final Response<SearchResult> response = LdapUtils.executeSearchOperation(this.connectionFactory, ldapProperties.getBaseDn(), filter); LOGGER.debug("LDAP response: [{}]", response); return LdapUtils.containsResultEntry(response); } catch (final Exception e) { LOGGER.error(e.getMessage(), e); } return false; } @Override public Collection<String> getEligibleAccountsForSurrogateToProxy(final String username) { final Collection<String> eligible = new LinkedHashSet<>(); try { final SearchFilter filter = Beans.newLdaptiveSearchFilter(ldapProperties.getSearchFilter(), Arrays.asList(username)); LOGGER.debug("Using search filter: [{}]", filter); final Response<SearchResult> response = LdapUtils.executeSearchOperation(this.connectionFactory, ldapProperties.getBaseDn(), filter); LOGGER.debug("LDAP response: [{}]", response); if (!LdapUtils.containsResultEntry(response)) { return eligible; } final LdapEntry ldapEntry = response.getResult().getEntry(); final LdapAttribute attribute = ldapEntry.getAttribute(ldapProperties.getMemberAttributeName()); if (attribute == null || attribute.getStringValues().isEmpty()) { return eligible; } final Pattern pattern = RegexUtils.createPattern(ldapProperties.getMemberAttributeValueRegex()); eligible.addAll( attribute.getStringValues() .stream() .map(pattern::matcher) .filter(Matcher::matches) .map(p -> p.group(1)) .collect(Collectors.toList())); } catch (final Exception e) { LOGGER.error(e.getMessage(), e); } return eligible; } }