Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/*
************************************************************************
******************* CANADIAN ASTRONOMY DATA CENTRE *******************
************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES **************
*
* (c) 2014. (c) 2014.
* Government of Canada Gouvernement du Canada
* National Research Council Conseil national de recherches
* Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6
* All rights reserved Tous droits réservés
*
* NRC disclaims any warranties, Le CNRC dénie toute garantie
* expressed, implied, or énoncée, implicite ou légale,
* statutory, of any kind with de quelque nature que ce
* respect to the software, soit, concernant le logiciel,
* including without limitation y compris sans restriction
* any warranty of merchantability toute garantie de valeur
* or fitness for a particular marchande ou de pertinence
* purpose. NRC shall not be pour un usage particulier.
* liable in any event for any Le CNRC ne pourra en aucun cas
* damages, whether direct or être tenu responsable de tout
* indirect, special or general, dommage, direct ou indirect,
* consequential or incidental, particulier ou général,
* arising from the use of the accessoire ou fortuit, résultant
* software. Neither the name de l'utilisation du logiciel. Ni
* of the National Research le nom du Conseil National de
* Council of Canada nor the Recherches du Canada ni les noms
* names of its contributors may de ses participants ne peuvent
* be used to endorse or promote être utilisés pour approuver ou
* products derived from this promouvoir les produits dérivés
* software without specific prior de ce logiciel sans autorisation
* written permission. préalable et particulière
* par écrit.
*
* This file is part of the Ce fichier fait partie du projet
* OpenCADC project. OpenCADC.
*
* OpenCADC is free software: OpenCADC est un logiciel libre ;
* you can redistribute it and/or vous pouvez le redistribuer ou le
* modify it under the terms of modifier suivant les termes de
* the GNU Affero General Public la “GNU Affero General Public
* License as published by the License” telle que publiée
* Free Software Foundation, par la Free Software Foundation
* either version 3 of the : soit la version 3 de cette
* License, or (at your option) licence, soit (à votre gré)
* any later version. toute version ultérieure.
*
* OpenCADC is distributed in the OpenCADC est distribué
* hope that it will be useful, dans l’espoir qu’il vous
* but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE
* without even the implied GARANTIE : sans même la garantie
* warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ
* or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF
* PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence
* General Public License for Générale Publique GNU Affero
* more details. pour plus de détails.
*
* You should have received Vous devriez avoir reçu une
* a copy of the GNU Affero copie de la Licence Générale
* General Public License along Publique GNU Affero avec
* with OpenCADC. If not, see OpenCADC ; si ce n’est
* <http://www.gnu.org/licenses/>. pas le cas, consultez :
* <http://www.gnu.org/licenses/>.
*
* $Revision: 4 $
*
************************************************************************
*/
package ca.nrc.cadc.ac.server.ldap;
import java.security.AccessControlException;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import javax.security.auth.x500.X500Principal;
import org.apache.log4j.Logger;
import ca.nrc.cadc.ac.Group;
import ca.nrc.cadc.ac.PersonalDetails;
import ca.nrc.cadc.ac.PosixDetails;
import ca.nrc.cadc.ac.User;
import ca.nrc.cadc.ac.UserAlreadyExistsException;
import ca.nrc.cadc.ac.UserDetails;
import ca.nrc.cadc.ac.UserNotFoundException;
import ca.nrc.cadc.ac.UserRequest;
import ca.nrc.cadc.auth.AuthenticationUtil;
import ca.nrc.cadc.auth.DNPrincipal;
import ca.nrc.cadc.auth.NumericPrincipal;
import ca.nrc.cadc.profiler.Profiler;
import ca.nrc.cadc.util.StringUtil;
import com.unboundid.ldap.sdk.AddRequest;
import com.unboundid.ldap.sdk.Attribute;
import com.unboundid.ldap.sdk.BindRequest;
import com.unboundid.ldap.sdk.BindResult;
import com.unboundid.ldap.sdk.DN;
import com.unboundid.ldap.sdk.DeleteRequest;
import com.unboundid.ldap.sdk.Filter;
import com.unboundid.ldap.sdk.LDAPException;
import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.LDAPSearchException;
import com.unboundid.ldap.sdk.Modification;
import com.unboundid.ldap.sdk.ModificationType;
import com.unboundid.ldap.sdk.ModifyDNRequest;
import com.unboundid.ldap.sdk.ResultCode;
import com.unboundid.ldap.sdk.SearchRequest;
import com.unboundid.ldap.sdk.SearchResult;
import com.unboundid.ldap.sdk.SearchResultEntry;
import com.unboundid.ldap.sdk.SearchScope;
import com.unboundid.ldap.sdk.SimpleBindRequest;
import com.unboundid.ldap.sdk.extensions.PasswordModifyExtendedRequest;
import com.unboundid.ldap.sdk.extensions.PasswordModifyExtendedResult;
/**
* @author pdowler
*/
public class LdapUserDAO<T extends Principal> extends LdapDAO
{
private static final Logger logger = Logger.getLogger(LdapUserDAO.class);
private final Profiler profiler = new Profiler(LdapUserDAO.class);
private final Map<Class<?>, String> userLdapAttrib = new HashMap<Class<?>, String>();
// Returned User attributes
protected static final String LDAP_OBJECT_CLASS = "objectClass";
protected static final String LDAP_INET_USER = "inetuser";
protected static final String LDAP_INET_ORG_PERSON = "inetOrgPerson";
protected static final String LDAP_CADC_ACCOUNT = "cadcaccount";
protected static final String LDAP_NSACCOUNTLOCK = "nsaccountlock";
protected static final String LDAP_MEMBEROF = "memberOf";
protected static final String LDAP_ENTRYDN = "entrydn";
protected static final String LDAP_COMMON_NAME = "cn";
protected static final String LDAP_DISTINGUISHED_NAME = "distinguishedName";
protected static final String LDAP_NUMERICID = "numericid";
protected static final String LADP_USER_PASSWORD = "userPassword";
protected static final String LDAP_FIRST_NAME = "givenName";
protected static final String LDAP_LAST_NAME = "sn";
protected static final String LDAP_ADDRESS = "address";
protected static final String LDAP_CITY = "city";
protected static final String LDAP_COUNTRY = "country";
protected static final String LDAP_EMAIL = "email";
protected static final String LDAP_INSTITUTE = "institute";
protected static final String LDAP_UID = "uid";
private String[] userAttribs = new String[]
{
LDAP_FIRST_NAME, LDAP_LAST_NAME, LDAP_ADDRESS, LDAP_CITY,
LDAP_COUNTRY, LDAP_EMAIL, LDAP_INSTITUTE
};
private String[] firstLastAttribs = new String[]
{
LDAP_FIRST_NAME, LDAP_LAST_NAME
};
private String[] identityAttribs = new String[]
{
LDAP_UID, LDAP_DISTINGUISHED_NAME, LDAP_NUMERICID, LDAP_ENTRYDN,
LDAP_MEMBEROF // for group cache
};
public LdapUserDAO(LdapConnections connections)
this.userLdapAttrib.put(HttpPrincipal.class, LDAP_UID);
this.userLdapAttrib.put(X500Principal.class, LDAP_DISTINGUISHED_NAME);
this.userLdapAttrib.put(NumericPrincipal.class, LDAP_NUMERICID);
// add the id attributes to user and member attributes
String[] princs = userLdapAttrib.values()
.toArray(new String[userLdapAttrib.values().size()]);
String[] tmp = new String[userAttribs.length + princs.length];
System.arraycopy(princs, 0, tmp, 0, princs.length);
System.arraycopy(userAttribs, 0, tmp, princs.length,
userAttribs.length);
tmp = new String[firstLastAttribs.length + princs.length];
System.arraycopy(princs, 0, tmp, 0, princs.length);
System.arraycopy(firstLastAttribs, 0, tmp, princs.length,
firstLastAttribs.length);
firstLastAttribs = tmp;
/**
* Verifies the username and password for an existing User.
*
* @param username username to verify.
* @param password password to verify.
* @return Boolean
* @throws UserNotFoundExceptionjoellama
public Boolean doLogin(final String username, final String password)
throws TransientException, UserNotFoundException
{
try
{
Jeff Burke
committed
BindRequest bindRequest = new SimpleBindRequest(
Patrick Dowler
committed
getUserDN(username, config.getUsersDN()), new String(password));
LDAPConnection conn = this.getUnboundReadConnection();
BindResult bindResult = conn.bind(bindRequest);
if (bindResult != null && bindResult.getResultCode() == ResultCode.SUCCESS)
{
return Boolean.TRUE;
}
else
{
throw new AccessControlException("Invalid username or password");
}
}
catch (LDAPException e)
{
logger.debug("doLogin Exception: " + e, e);
if (e.getResultCode() == ResultCode.INVALID_CREDENTIALS)
{
throw new AccessControlException("Invalid password");
}
else if (e.getResultCode() == ResultCode.NO_SUCH_OBJECT)
{
throw new AccessControlException("Invalid username");
}
else if (e.getResultCode() == ResultCode.UNWILLING_TO_PERFORM)
throw new AccessControlException("Account inactivated");
throw new RuntimeException("Unexpected LDAP exception", e);
Brian Major
committed
Jeff Burke
committed
* Add the specified user to the active user tree.
Jeff Burke
committed
* @param userRequest The user to add.
* @throws TransientException If an temporary, unexpected problem occurred.
* @throws UserAlreadyExistsException If the user already exists.
public void addUser(final UserRequest<T> userRequest)
throws TransientException, UserAlreadyExistsException
Jeff Burke
committed
try
{
getUser(userRequest.getUser().getUserID(), config.getUsersDN());
final String error = userRequest.getUser().getUserID().getName() +
" found in " + config.getUsersDN();
Jeff Burke
committed
throw new UserAlreadyExistsException(error);
}
catch (UserNotFoundException e1) {}
Jeff Burke
committed
addUser(userRequest, config.getUsersDN());
Jeff Burke
committed
*Add the specified user to the pending user tree.
*
* @param userRequest The user to add.
* @throws TransientException If an temporary, unexpected problem occurred.
* @throws UserAlreadyExistsException If the user already exists.
Jeff Burke
committed
public void addPendingUser(final UserRequest<T> userRequest)
throws TransientException, UserAlreadyExistsException
// check current users
Jeff Burke
committed
try
{
getUser(userRequest.getUser().getUserID(), config.getUsersDN(), false);
Jeff Burke
committed
final String error = userRequest.getUser().getUserID().getName() +
" found in " + config.getUsersDN();
Jeff Burke
committed
throw new UserAlreadyExistsException(error);
}
catch (UserNotFoundException ok) { }
// check pending users
try
Jeff Burke
committed
{
getUser(userRequest.getUser().getUserID(), config.getUserRequestsDN(), false);
final String error = userRequest.getUser().getUserID().getName() +
" found in " + config.getUserRequestsDN();
throw new UserAlreadyExistsException(error);
Jeff Burke
committed
}
catch (UserNotFoundException ok) { }
Jeff Burke
committed
Jeff Burke
committed
addUser(userRequest, config.getUserRequestsDN());
Jeff Burke
committed
private void addUser(final UserRequest<T> userRequest, final String usersDN)
throws TransientException, UserAlreadyExistsException
final User<T> user = userRequest.getUser();
final Class userType = user.getUserID().getClass();
final String searchField = userLdapAttrib.get(userType);
throw new IllegalArgumentException("Unsupported principal type " + userType);
try
{
List<Attribute> attributes = new ArrayList<Attribute>();
addAttribute(attributes, LDAP_OBJECT_CLASS, LDAP_INET_ORG_PERSON);
addAttribute(attributes, LDAP_OBJECT_CLASS, LDAP_INET_USER);
addAttribute(attributes, LDAP_OBJECT_CLASS, LDAP_CADC_ACCOUNT);
Jeff Burke
committed
addAttribute(attributes, LDAP_COMMON_NAME, user.getUserID().getName());
addAttribute(attributes, LADP_USER_PASSWORD, new String(userRequest.getPassword()));
addAttribute(attributes, LDAP_NUMERICID, String.valueOf(genNextNumericId()));
for (Principal princ : user.getIdentities())
{
if (princ instanceof X500Principal)
{
Jeff Burke
committed
addAttribute(attributes, LDAP_DISTINGUISHED_NAME, princ.getName());
for (UserDetails details : user.details)
{
if (details.getClass() == PersonalDetails.class)
{
PersonalDetails pd = (PersonalDetails) details;
addAttribute(attributes, LDAP_FIRST_NAME, pd.getFirstName());
addAttribute(attributes, LDAP_LAST_NAME, pd.getLastName());
addAttribute(attributes, LDAP_ADDRESS, pd.address);
addAttribute(attributes, LDAP_CITY, pd.city);
addAttribute(attributes, LDAP_COUNTRY, pd.country);
addAttribute(attributes, LDAP_EMAIL, pd.email);
addAttribute(attributes, LDAP_INSTITUTE, pd.institute);
}
else if (details.getClass() == PosixDetails.class)
{
throw new UnsupportedOperationException(
"Support for users PosixDetails not available");
Jeff Burke
committed
DN userDN = getUserDN(user.getUserID().getName(), usersDN);
AddRequest addRequest = new AddRequest(userDN, attributes);
LDAPResult result = getReadWriteConnection().add(addRequest);
LdapDAO.checkLdapResult(result.getResultCode());
}
catch (LDAPException e)
{
logger.error("addUser Exception: " + e, e);
LdapUserDAO.checkUserLDAPResult(e.getResultCode());
throw new RuntimeException("Unexpected LDAP exception", e);
}
}
* @throws UserNotFoundException when the user is not found in the main tree.
* @throws TransientException If an temporary, unexpected problem occurred.
* @throws AccessControlException If the operation is not permitted.
public User<T> getUser(final T userID)
throws UserNotFoundException, TransientException,
AccessControlException
{
return getUser(userID, config.getUsersDN());
}
/**
* Get the user specified by the email address exists.
*
* @param emailAddress The user's email address.
*
* @return User instance.
*
* @throws UserNotFoundException when the user is not found in the main tree.
* @throws TransientException If an temporary, unexpected problem occurred.
* @throws AccessControlException If the operation is not permitted.
*/
public User<Principal> getUserByEmailAddress(final String emailAddress)
throws UserNotFoundException, TransientException,
AccessControlException
{
return getUserByEmailAddress(emailAddress, config.getUsersDN(), true);
}
/**
* Obtain a user who is awaiting approval.
*
* @param userID The user ID of the pending user.
* @return A User instance awaiting approval.
*
* @throws UserNotFoundException when the user is not found in the user request tree.
* @throws TransientException If an temporary, unexpected problem occurred.
* @throws AccessControlException If the operation is not permitted.
*/
public User<T> getPendingUser(final T userID)
throws UserNotFoundException, TransientException,
AccessControlException
{
return getUser(userID, config.getUserRequestsDN());
}
/**
* Get the user specified by userID.
*
* @param userID The userID.
* @param usersDN The LDAP tree to search.
* @return User instance.
* @throws UserNotFoundException when the user is not found.
* @throws TransientException If an temporary, unexpected problem occurred.
* @throws AccessControlException If the operation is not permitted.
*/
private User<T> getUser(final T userID, final String usersDN)
throws UserNotFoundException, TransientException,
AccessControlException
return getUser(userID, usersDN, true);
}
/**
* Get the user specified by userID.
*
* @param userID The userID.
* @param usersDN The LDAP tree to search.
* @param proxy Whether to proxy the search as the calling Subject.
* @return User instance.
* @throws UserNotFoundException when the user is not found.
* @throws TransientException If an temporary, unexpected problem occurred.
* @throws AccessControlException If the operation is not permitted.
*/
private User<T> getUser(final T userID, final String usersDN, final boolean proxy)
throws UserNotFoundException, TransientException,
AccessControlException
{
String searchField = userLdapAttrib.get(userID.getClass());
throw new IllegalArgumentException(
"Unsupported principal type " + userID.getClass());
}
SearchResultEntry searchResult = null;
Filter filter = null;
filter = Filter.createEqualityFilter(searchField, userID.getName());
Jeff Burke
committed
logger.debug("search filter: " + filter);
new SearchRequest(usersDN, SearchScope.ONE, filter, userAttribs);
Jeff Burke
committed
//if (proxy)
//{
// String proxyDN = "dn:" + getSubjectDN().toNormalizedString();
// logger.debug("Proxying auth as: " + proxyDN);
// searchRequest.addControl(new ProxiedAuthorizationV2RequestControl(proxyDN));
//}
searchResult = getReadOnlyConnection().searchForEntry(searchRequest);
LdapDAO.checkLdapResult(e.getResultCode());
// determine if the user is not there of if the calling user
// doesn't have permission to see it
SearchRequest searchRequest =
new SearchRequest(usersDN, SearchScope.ONE, filter, userAttribs);
try
{
searchResult = getReadOnlyConnection().searchForEntry(searchRequest);
}
catch (LDAPException e)
{
LdapDAO.checkLdapResult(e.getResultCode());
}
if (searchResult == null)
{
String msg = "User not found " + userID.toString();
logger.debug(msg);
throw new UserNotFoundException(msg);
}
throw new AccessControlException("Permission denied");
User<T> user = new User<T>(userID);
String username = searchResult.getAttributeValue(userLdapAttrib.get(HttpPrincipal.class));
logger.debug("username: " + username);
user.getIdentities().add(new HttpPrincipal(username));
Integer numericID = searchResult.getAttributeValueAsInteger(userLdapAttrib.get(NumericPrincipal.class));
logger.debug("Numeric id: " + numericID);
if (numericID == null)
{
// If the numeric ID does not return it means the user
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
// does not have permission
throw new AccessControlException("Permission denied");
}
user.getIdentities().add(new NumericPrincipal(numericID));
String x500str = searchResult.getAttributeValue(userLdapAttrib.get(X500Principal.class));
logger.debug("x500principal: " + x500str);
if (x500str != null)
user.getIdentities().add(new X500Principal(x500str));
String fname = searchResult.getAttributeValue(LDAP_FIRST_NAME);
String lname = searchResult.getAttributeValue(LDAP_LAST_NAME);
PersonalDetails personaDetails = new PersonalDetails(fname, lname);
personaDetails.address = searchResult.getAttributeValue(LDAP_ADDRESS);
personaDetails.city = searchResult.getAttributeValue(LDAP_CITY);
personaDetails.country = searchResult.getAttributeValue(LDAP_COUNTRY);
personaDetails.email = searchResult.getAttributeValue(LDAP_EMAIL);
personaDetails.institute = searchResult.getAttributeValue(LDAP_INSTITUTE);
user.details.add(personaDetails);
return user;
}
/**
* Get the user specified by the email address exists.
*
* @param emailAddress The user's email address.
* @param usersDN The LDAP tree to search.
* @param proxy Whether to proxy the search as the calling Subject.
* @return User ID
* @throws UserNotFoundException when the user is not found.
* @throws TransientException If an temporary, unexpected problem occurred.
* @throws AccessControlException If the operation is not permitted.
*/
private User<Principal> getUserByEmailAddress(final String emailAddress,
final String usersDN, final boolean proxy)
throws UserNotFoundException, TransientException,
AccessControlException
{
SearchResultEntry searchResult = null;
Filter filter = null;
try
{
filter = Filter.createEqualityFilter("email", emailAddress);
logger.debug("search filter: " + filter);
SearchRequest searchRequest =
new SearchRequest(usersDN, SearchScope.ONE, filter, userAttribs);
searchResult = getReadOnlyConnection().searchForEntry(searchRequest);
}
catch (LDAPException e)
{
LdapDAO.checkLdapResult(e.getResultCode());
}
if (searchResult == null)
{
// determine if the user is not there of if the calling user
// doesn't have permission to see it
SearchRequest searchRequest =
new SearchRequest(usersDN, SearchScope.ONE, filter, userAttribs);
try
{
searchResult = getReadOnlyConnection().searchForEntry(searchRequest);
}
catch (LDAPException e)
{
LdapDAO.checkLdapResult(e.getResultCode());
}
if (searchResult == null)
{
String msg = "User with email address " + emailAddress + " not found";
logger.debug(msg);
throw new UserNotFoundException(msg);
}
throw new AccessControlException("Permission denied");
}
String userIDString = searchResult.getAttributeValue(LDAP_UID);
HttpPrincipal userID = new HttpPrincipal(userIDString);
User<Principal> user = new User<Principal>(userID);
String username = searchResult.getAttributeValue(userLdapAttrib.get(HttpPrincipal.class));
logger.debug("username: " + username);
user.getIdentities().add(new HttpPrincipal(username));
Integer numericID = searchResult.getAttributeValueAsInteger(userLdapAttrib.get(NumericPrincipal.class));
logger.debug("Numeric id: " + numericID);
if (numericID == null)
{
// If the numeric ID does not return it means the user
// does not have permission
throw new AccessControlException("Permission denied");
}
user.getIdentities().add(new NumericPrincipal(numericID));
String x500str = searchResult.getAttributeValue(userLdapAttrib.get(X500Principal.class));
logger.debug("x500principal: " + x500str);
if (x500str != null)
user.getIdentities().add(new X500Principal(x500str));
String fname = searchResult.getAttributeValue(LDAP_FIRST_NAME);
String lname = searchResult.getAttributeValue(LDAP_LAST_NAME);
PersonalDetails personaDetails = new PersonalDetails(fname, lname);
personaDetails.address = searchResult.getAttributeValue(LDAP_ADDRESS);
personaDetails.city = searchResult.getAttributeValue(LDAP_CITY);
personaDetails.country = searchResult.getAttributeValue(LDAP_COUNTRY);
personaDetails.email = searchResult.getAttributeValue(LDAP_EMAIL);
personaDetails.institute = searchResult.getAttributeValue(LDAP_INSTITUTE);
user.details.add(personaDetails);
public User<T> getAugmentedUser(final T userID)
throws UserNotFoundException, TransientException
{
String searchField = userLdapAttrib.get(userID.getClass());
profiler.checkpoint("getAugmentedUser.getSearchField");
if (searchField == null)
{
throw new IllegalArgumentException(
"Unsupported principal type " + userID.getClass());
}
try
{
Filter filter = Filter.createEqualityFilter(searchField, userID.getName());
profiler.checkpoint("getAugmentedUser.createFilter");
Jeff Burke
committed
logger.debug("search filter: " + filter);
Jeff Burke
committed
SearchRequest searchRequest = new SearchRequest(
config.getUsersDN(), SearchScope.ONE, filter, identityAttribs);
profiler.checkpoint("getAugmentedUser.createSearchRequest");
SearchResultEntry searchResult = getReadOnlyConnection().searchForEntry(searchRequest);
profiler.checkpoint("getAugmentedUser.searchForEntry");
if (searchResult == null)
{
String msg = "User not found " + userID.toString();
logger.debug(msg);
throw new UserNotFoundException(msg);
}
User<T> user = new User<T>(userID);
user.getIdentities().add(new HttpPrincipal(
searchResult.getAttributeValue(LDAP_UID)));
int numericID = searchResult.getAttributeValueAsInteger(LDAP_NUMERICID);
logger.debug("numericID is " + numericID);
user.getIdentities().add(new NumericPrincipal(numericID));
String dn = searchResult.getAttributeValue(LDAP_DISTINGUISHED_NAME);
if (dn != null)
{
user.getIdentities().add(new X500Principal(dn));
}
user.getIdentities().add(new DNPrincipal(searchResult.getAttributeValue(LDAP_ENTRYDN)));
// cache memberOf values in the user
GroupMemberships gms = new GroupMemberships(user);
user.appData = gms; // add even if empty
String[] mems = searchResult.getAttributeValues(LDAP_MEMBEROF);
if (mems != null && mems.length > 0)
{
DN adminDN = new DN(config.getAdminGroupsDN());
DN groupsDN = new DN(config.getGroupsDN());
List<Group> memberOf = new ArrayList<Group>();
List<Group> adminOf = new ArrayList<Group>();
for (String m : mems)
{
DN groupDN = new DN(m);
if (groupDN.isDescendantOf(groupsDN, false))
memberOf.add(createGroupFromDN(groupDN));
else if (groupDN.isDescendantOf(adminDN, false))
adminOf.add(createGroupFromDN(groupDN));
}
gms.add(adminOf, Role.ADMIN);
gms.add(memberOf, Role.MEMBER);
}
profiler.checkpoint("getAugmentedUser.mapIdentities");
return user;
}
catch (LDAPException e)
{
logger.debug("getGroup Exception: " + e, e);
LdapDAO.checkLdapResult(e.getResultCode());
throw new RuntimeException("BUG: checkLdapResult didn't throw an exception");
}
finally
{
profiler.checkpoint("Done getAugmentedUser");
}
// some pretty horrible hacks to avoid querying LDAP for group details...
private Group createGroupFromDN(DN groupDN)
{
String cn = groupDN.getRDNString();
String[] parts = cn.split("=");
if (parts.length == 2 && parts[0].equals("cn"))
{
return new Group(parts[1]);
}
throw new RuntimeException("BUG: failed to extract group name from " + groupDN
.toString());
}
Jeff Burke
committed
* Get all users from the active tree.
Jeff Burke
committed
* @return A Collection of User's.
* @throws TransientException If an temporary, unexpected problem occurred.
Jeff Burke
committed
public Collection<User<Principal>> getUsers()
throws AccessControlException, TransientException
Jeff Burke
committed
return getUsers(config.getUsersDN());
Jeff Burke
committed
* Get all users from the pending tree.
Jeff Burke
committed
* @return A Collection of User's.
* @throws TransientException If an temporary, unexpected problem occurred.
*/
Jeff Burke
committed
public Collection<User<Principal>> getPendingUsers()
throws AccessControlException, TransientException
Jeff Burke
committed
{
return getUsers(config.getUserRequestsDN());
}
private Collection<User<Principal>> getUsers(final String usersDN)
throws AccessControlException, TransientException
final Collection<User<Principal>> users = new ArrayList<User<Principal>>();
Filter filter = Filter.createPresenceFilter(LDAP_UID);
logger.debug("search filter: " + filter);
Jeff Burke
committed
final String[] attributes = new String[]
{ LDAP_UID, LDAP_FIRST_NAME, LDAP_LAST_NAME };
final SearchRequest searchRequest =
new SearchRequest(usersDN, SearchScope.ONE, filter, attributes);
try
{
final SearchResult searchResult =
getReadOnlyConnection().search(searchRequest);
LdapDAO.checkLdapResult(searchResult.getResultCode());
for (SearchResultEntry next : searchResult.getSearchEntries())
final String firstName =
next.getAttributeValue(LDAP_FIRST_NAME).trim();
final String lastName =
next.getAttributeValue(LDAP_LAST_NAME).trim();
final String uid = next.getAttributeValue(LDAP_UID).trim();
User<Principal> user = new User<Principal>(new HttpPrincipal(uid));
// Only add Personal Details if it is relevant.
if (StringUtil.hasLength(firstName)
&& StringUtil.hasLength(lastName))
{
user.details.add(new PersonalDetails(firstName, lastName));
}
catch (LDAPSearchException e)
if (e.getResultCode() == ResultCode.NO_SUCH_OBJECT)
{
final String message = "Could not find users root";
logger.debug(message, e);
throw new IllegalStateException(message);
}
* Move the pending user specified by userID from the
* pending users tree to the active users tree.
* @param userID
* @return User instance.
* @throws UserNotFoundException when the user is not found.
* @throws TransientException If an temporary, unexpected problem occurred.
* @throws AccessControlException If the operation is not permitted.
*/
public User<T> approvePendingUser(final T userID)
throws UserNotFoundException, TransientException, AccessControlException
{
User<T> pendingUser = getPendingUser(userID);
Set<HttpPrincipal> httpPrincipals = pendingUser.getIdentities(HttpPrincipal.class);
if (httpPrincipals.isEmpty())
{
throw new RuntimeException("BUG: missing HttpPrincipal for " + userID.getName());
}
HttpPrincipal httpPrincipal = httpPrincipals.iterator().next();
String uid = "uid=" + httpPrincipal.getName();
String dn = uid + "," + config.getUserRequestsDN();
try
{
ModifyDNRequest modifyDNRequest =
new ModifyDNRequest(dn, uid, true, config.getUsersDN());
LdapDAO.checkLdapResult(getReadWriteConnection().modifyDN(modifyDNRequest).getResultCode());
}
catch (LDAPException e)
{
logger.debug("Modify Exception", e);
LdapDAO.checkLdapResult(e.getResultCode());
}
try
{
return getUser(userID);
}
catch (UserNotFoundException e)
{
throw new RuntimeException(
"BUG: approved user not found (" + userID.getName() + ")");
}
}
/**
* Update the user specified by User.
*
* @param userID
* @throws UserNotFoundException when the user is not found.
* @throws TransientException If an temporary, unexpected problem occurred.
* @throws AccessControlException If the operation is not permitted.
*/
public User<T> modifyUser(final User<T> userID)
throws UserNotFoundException, TransientException, AccessControlException
User existingUser = getUser(userID.getUserID());
List<Modification> mods = new ArrayList<Modification>();
for (UserDetails details : userID.details)
{
if (details.getClass() == PersonalDetails.class)
{
PersonalDetails pd = (PersonalDetails) details;
addModification(mods, LDAP_FIRST_NAME, pd.getFirstName());
addModification(mods, LDAP_LAST_NAME, pd.getLastName());
addModification(mods, LDAP_ADDRESS, pd.address);
addModification(mods, LDAP_CITY, pd.city);
addModification(mods, LDAP_COUNTRY, pd.country);
addModification(mods, LDAP_EMAIL, pd.email);
addModification(mods, LDAP_INSTITUTE, pd.institute);
}
else if (details.getClass() == PosixDetails.class)
{
throw new UnsupportedOperationException(
"Support for users PosixDetails not available");
// set the x500 DNs if there
Set<X500Principal> x500Principals = userID.getIdentities(X500Principal.class);
if (x500Principals != null && !x500Principals.isEmpty())
{
Iterator<X500Principal> i = x500Principals.iterator();
X500Principal next = null;
while (i.hasNext())
{
next = i.next();
addModification(mods, LDAP_DISTINGUISHED_NAME, next.getName());
}
}
ModifyRequest modifyRequest = new ModifyRequest(getUserDN(userID), mods);
//modifyRequest.addControl(
// new ProxiedAuthorizationV2RequestControl(
// "dn:" + getSubjectDN().toNormalizedString()));
LdapDAO.checkLdapResult(getReadWriteConnection().modify(modifyRequest).getResultCode());
logger.debug("Modify Exception", e);
LdapDAO.checkLdapResult(e.getResultCode());
return getUser(userID.getUserID());
}
catch (UserNotFoundException e)
{
throw new RuntimeException(
"BUG: modified user not found (" + userID.getUserID() + ")");
Alinga Yeung
committed
protected void updatePassword(HttpPrincipal userID, String oldPassword, String newPassword)
throws UserNotFoundException, TransientException, AccessControlException
Patrick Dowler
committed
User user = new User(userID);
Patrick Dowler
committed
//BindRequest bindRequest = new SimpleBindRequest(
// getUserDN(username, config.getUsersDN()), oldPassword);
//LDAPConnection conn = this.getUnboundReadConnection();
//conn.bind(bindRequest);
Patrick Dowler
committed
LDAPConnection conn = this.getReadWriteConnection();
Alinga Yeung
committed
PasswordModifyExtendedRequest passwordModifyRequest;
if (StringUtil.hasText(oldPassword))
{
passwordModifyRequest =
new PasswordModifyExtendedRequest(
userDN.toNormalizedString(), new String(oldPassword), new String(newPassword));
}
else
{
passwordModifyRequest =
new PasswordModifyExtendedRequest(
userDN.toNormalizedString(), new String(newPassword));
}
PasswordModifyExtendedResult passwordModifyResult = (PasswordModifyExtendedResult)
conn.processExtendedOperation(passwordModifyRequest);
LdapDAO.checkLdapResult(passwordModifyResult.getResultCode());
}
catch (LDAPException e)
{
logger.debug("setPassword Exception: " + e);
LdapDAO.checkLdapResult(e.getResultCode());
}
Alinga Yeung
committed
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
/**
* Update a user's password. The given user and authenticating user must match.
*
* @param userID
* @param oldPassword current password.
* @param newPassword new password.
* @throws UserNotFoundException If the given user does not exist.
* @throws TransientException If an temporary, unexpected problem occurred.
* @throws AccessControlException If the operation is not permitted.
*/
public void setPassword(HttpPrincipal userID, String oldPassword, String newPassword)
throws UserNotFoundException, TransientException, AccessControlException
{
updatePassword(userID, oldPassword, newPassword);
}
/**
* Reset a user's password. The given user and authenticating user must match.
*
* @param userID
* @param newPassword new password.
* @throws UserNotFoundException If the given user does not exist.
* @throws TransientException If an temporary, unexpected problem occurred.
* @throws AccessControlException If the operation is not permitted.
*/
public void resetPassword(HttpPrincipal userID, String newPassword)
throws UserNotFoundException, TransientException, AccessControlException
{
updatePassword(userID, "", newPassword);
}
Jeff Burke
committed
* Delete the user specified by userID from the active user tree.
*
* @param userID The userID.
* @throws UserNotFoundException when the user is not found.
* @throws TransientException If an temporary, unexpected problem occurred.
* @throws AccessControlException If the operation is not permitted.
*/
public void deleteUser(final T userID)