Skip to content

Commit

Permalink
SAK-40572 Add 4 additional config options to the unboundid LDAP provi…
Browse files Browse the repository at this point in the history
…der (sakaiproject#5965)

allowAuthenticationAdmin (default false)
allowAuthenticationExternal (default true)
allowSearchExternal (default true)
allowGetExternal (default true)
  • Loading branch information
smarquard authored and ern committed Sep 10, 2018
1 parent d2e3cea commit 12cbbc4
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 3 deletions.
34 changes: 33 additions & 1 deletion providers/component/src/webapp/WEB-INF/unboundid-ldap.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
<bean id="org.sakaiproject.user.api.UserDirectoryProvider"
class="org.sakaiproject.unboundid.UnboundidDirectoryProvider" init-method="init"
destroy-method="destroy">

<property name="securityService" ref="org.sakaiproject.authz.api.SecurityService"/>

<!-- Required. Uses Unboundid SingleServerSet by default. Easy to modify code to use FailoverServerSet or RoundRobinServerSet. -->
<property name="ldapHost">
Expand Down Expand Up @@ -90,7 +92,37 @@
<!-- property name="allowAuthentication">
<value>true</value>
</property -->


<!-- Optional. Controls whether or not users who are super users (admin)
may be authenticated from the directory. Defaults to
UnboundidDirectoryProvider.DEFAULT_ALLOW_AUTHENTICATION_ADMIN -->
<!-- property name="allowAuthenticationAdmin">
<value>false</value>
</property -->

<!-- Optional. Controls whether or not external users (who are not in
the internal user database) can be authenticated from the directory.
If false, LDAP will authenticate internal users only. Defaults to
UnboundidDirectoryProvider.DEFAULT_ALLOW_AUTHENTICATION_EXTERNAL -->
<!-- property name="allowAuthenticationExternal">
<value>true</value>
</property -->

<!-- Optional. Control whether or not the directory may be searched for
users that match given search criteria. Defaults to
UnboundidDirectoryProvider.DEFAULT_ALLOW_SEARCH_EXTERNAL -->
<!-- property name="allowSearchExternal">
<value>true</value>
</property -->

<!-- Optional. Control whether or not external users (who are not in
the internal user database) can be loaded from the directory.
If false, LDAP will be used for authentication only. Defaults to
UnboundidDirectoryProvider.DEFAULT_ALLOW_GET_EXTERNAL -->
<!-- property name="allowGetExternal">
<value>true</value>
</property -->

<!-- Optional. Defaults to an instance of
org.sakaiproject.unboundid.SimpleLdapConnectionManager -->
<!-- property name="ldapConnectionManager">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,12 @@
import javax.net.ssl.SSLSocketFactory;

import lombok.extern.slf4j.Slf4j;
import lombok.Getter;
import lombok.Setter;

import org.apache.commons.lang3.StringUtils;

import org.sakaiproject.authz.api.SecurityService;
import org.sakaiproject.user.api.AuthenticationIdUDP;
import org.sakaiproject.user.api.DisplayAdvisorUDP;
import org.sakaiproject.user.api.ExternalUserSearchUDP;
Expand Down Expand Up @@ -69,6 +74,10 @@
@Slf4j
public class UnboundidDirectoryProvider implements UserDirectoryProvider, LdapConnectionManagerConfig, ExternalUserSearchUDP, UsersShareEmailUDP, DisplayAdvisorUDP, AuthenticationIdUDP
{

/** Security Service */
@Setter private SecurityService securityService;

/** Default LDAP connection port */
public static final int[] DEFAULT_LDAP_PORT = {389};

Expand Down Expand Up @@ -104,6 +113,14 @@ public class UnboundidDirectoryProvider implements UserDirectoryProvider, LdapCo
public static final String DISPLAY_NAME_PROPERTY = UnboundidDirectoryProvider.class+"-displayName";

public static final boolean DEFAULT_ALLOW_AUTHENTICATION = true;

public static final boolean DEFAULT_ALLOW_AUTHENTICATION_EXTERNAL = true;

public static final boolean DEFAULT_ALLOW_AUTHENTICATION_ADMIN = false;

public static final boolean DEFAULT_ALLOW_SEARCH_EXTERNAL = true;

public static final boolean DEFAULT_ALLOW_GET_EXTERNAL = true;

public static final boolean DEFAULT_AUTHENTICATE_WITH_PROVIDER_FIRST = false;

Expand Down Expand Up @@ -193,6 +210,28 @@ public Object mapLdapEntry(LDAPEntry searchResult, int resultNum) {
* Flag for allowing/disallowing authentication on a global basis
*/
private boolean allowAuthentication = DEFAULT_ALLOW_AUTHENTICATION;

/**
* Flag for allowing/disallowing authentication for external users (who do not already exist).
* If false, only users who have existing accounts may authenticate via LDAP.
*/
@Getter @Setter private boolean allowAuthenticationExternal = DEFAULT_ALLOW_AUTHENTICATION_EXTERNAL;

/**
* Flag for allowing/disallowing authentication for admin-equivalent users.
* If false, users who have admin-equivalent accounts may not authenticate via LDAP.
*/
@Getter @Setter private boolean allowAuthenticationAdmin = DEFAULT_ALLOW_AUTHENTICATION_ADMIN;

/**
* Flag for allowing/disallowing searching external users
*/
@Getter @Setter private boolean allowSearchExternal = DEFAULT_ALLOW_SEARCH_EXTERNAL;

/**
* Flag for allowing/disallowing getting an external user
*/
@Getter @Setter private boolean allowGetExternal = DEFAULT_ALLOW_GET_EXTERNAL;

/**
* Flag for controlling the return value of
Expand Down Expand Up @@ -341,8 +380,20 @@ public boolean authenticateUser(final String userLogin, final UserEdit edit, fin
return false;
}

if ( !allowAuthenticationExternal && (edit.getId() == null)) {
log.debug("authenticateUser(): returning false, not authenticating for external users");
return false;
}

if ( !allowAuthenticationAdmin && securityService.isSuperUser(edit.getId())) {
log.debug("authenticateUser(): returning false, not authenticating for superuser (admin) {}", edit.getEid());
return false;
}

try
{
long start = System.currentTimeMillis();

// look up the end-user's DN, which could be nested at some
// arbitrary depth below getBasePath().
// TODO: optimization opportunity if user entries are
Expand All @@ -359,6 +410,7 @@ public boolean authenticateUser(final String userLogin, final UserEdit edit, fin
lc = connectionPool.getConnection();
BindResult bindResult = lc.bind(endUserDN, password);
if(bindResult.getResultCode().equals(ResultCode.SUCCESS)) {
log.info("Authenticated {} ({}) from LDAP in {} ms", userLogin, endUserDN, System.currentTimeMillis() - start);
return true;
}

Expand All @@ -368,7 +420,7 @@ public boolean authenticateUser(final String userLogin, final UserEdit edit, fin
catch (com.unboundid.ldap.sdk.LDAPException e)
{
if (e.getResultCode().intValue() == LDAPException.INVALID_CREDENTIALS) {
log.warn("authenticateUser(): invalid credentials [userLogin = {}]", userLogin);
log.info("authenticateUser(): invalid credentials [userLogin = {}]", userLogin);
return false;
} else {
throw new RuntimeException(
Expand Down Expand Up @@ -465,6 +517,11 @@ public boolean findUserByEmail(UserEdit edit, String email)
public boolean getUser(UserEdit edit)
{

if (!allowGetExternal) {
log.debug("getUser() external get not enabled");
return false;
}

try {
return getUserByEid(edit, edit.getEid());
} catch ( LDAPException e ) {
Expand Down Expand Up @@ -1380,6 +1437,11 @@ public void setSearchScope(int searchScope) throws IllegalArgumentException {
* A list (UserEdit) of all the users matching the criteria.
*/
public List<UserEdit> searchExternalUsers(String criteria, int first, int last, UserFactory factory) {

if (!allowSearchExternal) {
log.debug("External search is disabled");
return null;
}

String filter = ldapAttributeMapper.getFindUserByCrossAttributeSearchFilter(criteria);
List<UserEdit> users = new ArrayList<UserEdit>();
Expand Down Expand Up @@ -1418,8 +1480,14 @@ public List<UserEdit> searchExternalUsers(String criteria, int first, int last,
@SuppressWarnings("rawtypes")
public Collection findUsersByEmail(String email, UserFactory factory) {

String filter = ldapAttributeMapper.getFindUserByEmailFilter(email);
List<User> users = new ArrayList<User>();

if (!allowSearchExternal) {
log.debug("External search is disabled");
return users;
}

String filter = ldapAttributeMapper.getFindUserByEmailFilter(email);
try {
List<LdapUserData> ldapUsers = searchDirectory(filter, null, null, null, maxResultSize);

Expand Down

0 comments on commit 12cbbc4

Please sign in to comment.