1 package org
.argeo
.osgi
.useradmin
;
3 import static org
.argeo
.osgi
.useradmin
.LdifName
.objectClass
;
5 import java
.util
.ArrayList
;
6 import java
.util
.Dictionary
;
7 import java
.util
.Hashtable
;
10 import javax
.naming
.Binding
;
11 import javax
.naming
.Context
;
12 import javax
.naming
.InvalidNameException
;
13 import javax
.naming
.NamingEnumeration
;
14 import javax
.naming
.NamingException
;
15 import javax
.naming
.directory
.Attributes
;
16 import javax
.naming
.directory
.DirContext
;
17 import javax
.naming
.directory
.SearchControls
;
18 import javax
.naming
.directory
.SearchResult
;
19 import javax
.naming
.ldap
.InitialLdapContext
;
20 import javax
.naming
.ldap
.LdapName
;
22 import org
.apache
.commons
.logging
.Log
;
23 import org
.apache
.commons
.logging
.LogFactory
;
24 import org
.argeo
.ArgeoException
;
25 import org
.osgi
.framework
.Filter
;
26 import org
.osgi
.service
.useradmin
.User
;
28 public class LdapUserAdmin
extends AbstractUserDirectory
{
29 private final static Log log
= LogFactory
.getLog(LdapUserAdmin
.class);
31 private InitialLdapContext initialLdapContext
= null;
33 public LdapUserAdmin(Dictionary
<String
, ?
> properties
) {
36 Hashtable
<String
, Object
> connEnv
= new Hashtable
<String
, Object
>();
37 connEnv
.put(Context
.INITIAL_CONTEXT_FACTORY
,
38 "com.sun.jndi.ldap.LdapCtxFactory");
39 connEnv
.put(Context
.PROVIDER_URL
, getUri().toString());
40 connEnv
.put("java.naming.ldap.attributes.binary",
41 LdifName
.userpassword
.name());
43 initialLdapContext
= new InitialLdapContext(connEnv
, null);
44 // StartTlsResponse tls = (StartTlsResponse) ctx
45 // .extendedOperation(new StartTlsRequest());
47 initialLdapContext
.addToEnvironment(
48 Context
.SECURITY_AUTHENTICATION
, "simple");
49 Object principal
= properties
.get(Context
.SECURITY_PRINCIPAL
);
50 if (principal
!= null) {
51 initialLdapContext
.addToEnvironment(Context
.SECURITY_PRINCIPAL
,
52 principal
.toString());
53 Object creds
= properties
.get(Context
.SECURITY_CREDENTIALS
);
55 initialLdapContext
.addToEnvironment(
56 Context
.SECURITY_CREDENTIALS
, creds
.toString());
60 // initialLdapContext.addToEnvironment(Context.SECURITY_PRINCIPAL,
61 // "uid=admin,ou=system");
62 // initialLdapContext.addToEnvironment(Context.SECURITY_CREDENTIALS,
64 } catch (Exception e
) {
65 throw new UserDirectoryException("Cannot connect to LDAP", e
);
69 public void destroy() {
72 initialLdapContext
.close();
73 } catch (NamingException e
) {
74 log
.error("Cannot destroy LDAP user admin", e
);
78 protected InitialLdapContext
getLdapContext() {
79 return initialLdapContext
;
83 protected Boolean
daoHasRole(LdapName dn
) {
84 return daoGetRole(dn
) != null;
88 protected DirectoryUser
daoGetRole(LdapName name
) {
90 Attributes attrs
= getLdapContext().getAttributes(name
);
91 if (attrs
.size() == 0)
94 if (attrs
.get(objectClass
.name()).contains(getGroupObjectClass()))
95 res
= new LdifGroup(this, name
, attrs
);
96 else if (attrs
.get(objectClass
.name()).contains(
97 getUserObjectClass()))
98 res
= new LdifUser(this, name
, attrs
);
100 throw new UserDirectoryException("Unsupported LDAP type for "
103 } catch (NamingException e
) {
104 throw new UserDirectoryException("Cannot get role for " + name
, e
);
109 protected List
<DirectoryUser
> doGetRoles(Filter f
) {
110 // TODO Auto-generated method stub
112 String searchFilter
= f
!= null ? f
.toString() : "(|("
113 + objectClass
+ "=" + getUserObjectClass() + ")("
114 + objectClass
+ "=" + getGroupObjectClass() + "))";
115 SearchControls searchControls
= new SearchControls();
116 searchControls
.setSearchScope(SearchControls
.SUBTREE_SCOPE
);
118 String searchBase
= getBaseDn();
119 NamingEnumeration
<SearchResult
> results
= getLdapContext().search(
120 searchBase
, searchFilter
, searchControls
);
122 ArrayList
<DirectoryUser
> res
= new ArrayList
<DirectoryUser
>();
123 while (results
.hasMoreElements()) {
124 SearchResult searchResult
= results
.next();
125 Attributes attrs
= searchResult
.getAttributes();
127 if (attrs
.get(objectClass
.name()).contains(
128 getGroupObjectClass()))
129 role
= new LdifGroup(this, toDn(searchBase
, searchResult
),
131 else if (attrs
.get(objectClass
.name()).contains(
132 getUserObjectClass()))
133 role
= new LdifUser(this, toDn(searchBase
, searchResult
),
136 throw new UserDirectoryException(
137 "Unsupported LDAP type for "
138 + searchResult
.getName());
142 } catch (Exception e
) {
143 throw new UserDirectoryException(
144 "Cannot get roles for filter " + f
, e
);
149 protected void doGetUser(String key
, String value
,
150 List
<DirectoryUser
> collectedUsers
) {
152 String searchFilter
= "(&(" + objectClass
+ "="
153 + getUserObjectClass() + ")(" + key
+ "=" + value
+ "))";
155 SearchControls searchControls
= new SearchControls();
156 searchControls
.setSearchScope(SearchControls
.SUBTREE_SCOPE
);
158 String searchBase
= getBaseDn();
159 NamingEnumeration
<SearchResult
> results
= getLdapContext().search(
160 searchBase
, searchFilter
, searchControls
);
162 SearchResult searchResult
= null;
163 if (results
.hasMoreElements()) {
164 searchResult
= (SearchResult
) results
.nextElement();
165 if (results
.hasMoreElements())
168 if (searchResult
!= null)
169 collectedUsers
.add(new LdifUser(this, toDn(searchBase
,
170 searchResult
), searchResult
.getAttributes()));
171 } catch (Exception e
) {
172 throw new UserDirectoryException("Cannot get user with " + key
178 private LdapName
toDn(String baseDn
, Binding binding
)
179 throws InvalidNameException
{
180 return new LdapName(binding
.isRelative() ? binding
.getName() + ","
181 + baseDn
: binding
.getName());
185 protected List
<DirectoryGroup
> getDirectGroups(User user
) {
186 List
<DirectoryGroup
> directGroups
= new ArrayList
<DirectoryGroup
>();
188 String searchFilter
= "(&(" + objectClass
+ "="
189 + getGroupObjectClass() + ")(" + getMemberAttributeId()
190 + "=" + user
.getName() + "))";
192 SearchControls searchControls
= new SearchControls();
193 searchControls
.setSearchScope(SearchControls
.SUBTREE_SCOPE
);
195 String searchBase
= getBaseDn();
196 NamingEnumeration
<SearchResult
> results
= getLdapContext().search(
197 searchBase
, searchFilter
, searchControls
);
199 while (results
.hasMoreElements()) {
200 SearchResult searchResult
= (SearchResult
) results
202 LdifGroup group
= new LdifGroup(this, toDn(searchBase
,
203 searchResult
), searchResult
.getAttributes());
204 directGroups
.add(group
);
207 } catch (Exception e
) {
208 throw new ArgeoException("Cannot populate direct members of "
214 protected void prepare(WorkingCopy wc
) {
216 getLdapContext().reconnect(getLdapContext().getConnectControls());
218 for (LdapName dn
: wc
.getDeletedUsers().keySet()) {
219 if (!entryExists(dn
))
220 throw new UserDirectoryException("User to delete no found "
224 for (LdapName dn
: wc
.getNewUsers().keySet()) {
225 if (!entryExists(dn
))
226 throw new UserDirectoryException("User to create found "
230 for (LdapName dn
: wc
.getModifiedUsers().keySet()) {
231 if (!entryExists(dn
))
232 throw new UserDirectoryException("User to modify no found "
235 } catch (NamingException e
) {
236 throw new UserDirectoryException("Cannot prepare LDAP", e
);
240 private boolean entryExists(LdapName dn
) throws NamingException
{
241 return getLdapContext().getAttributes(dn
).size() != 0;
245 protected void commit(WorkingCopy wc
) {
248 for (LdapName dn
: wc
.getDeletedUsers().keySet()) {
249 getLdapContext().destroySubcontext(dn
);
252 for (LdapName dn
: wc
.getNewUsers().keySet()) {
253 DirectoryUser user
= wc
.getNewUsers().get(dn
);
254 getLdapContext().createSubcontext(dn
, user
.getAttributes());
257 for (LdapName dn
: wc
.getModifiedUsers().keySet()) {
258 Attributes modifiedAttrs
= wc
.getModifiedUsers().get(dn
);
259 getLdapContext().modifyAttributes(dn
,
260 DirContext
.REPLACE_ATTRIBUTE
, modifiedAttrs
);
262 } catch (NamingException e
) {
263 throw new UserDirectoryException("Cannot commit LDAP", e
);
268 protected void rollback(WorkingCopy wc
) {
269 // prepare not impacting