1 package org
.argeo
.osgi
.useradmin
;
4 import java
.util
.ArrayList
;
5 import java
.util
.Hashtable
;
8 import javax
.naming
.Binding
;
9 import javax
.naming
.Context
;
10 import javax
.naming
.InvalidNameException
;
11 import javax
.naming
.NamingEnumeration
;
12 import javax
.naming
.NamingException
;
13 import javax
.naming
.directory
.Attributes
;
14 import javax
.naming
.directory
.SearchControls
;
15 import javax
.naming
.directory
.SearchResult
;
16 import javax
.naming
.ldap
.InitialLdapContext
;
17 import javax
.naming
.ldap
.LdapContext
;
18 import javax
.naming
.ldap
.LdapName
;
20 import org
.apache
.commons
.logging
.Log
;
21 import org
.apache
.commons
.logging
.LogFactory
;
22 import org
.argeo
.ArgeoException
;
23 import org
.osgi
.framework
.InvalidSyntaxException
;
24 import org
.osgi
.service
.useradmin
.Authorization
;
25 import org
.osgi
.service
.useradmin
.Group
;
26 import org
.osgi
.service
.useradmin
.Role
;
27 import org
.osgi
.service
.useradmin
.User
;
29 public class LdapUserAdmin
extends AbstractLdapUserAdmin
{
30 private final static Log log
= LogFactory
.getLog(LdapUserAdmin
.class);
32 private String baseDn
= "dc=example,dc=com";
33 private InitialLdapContext initialLdapContext
= null;
35 public LdapUserAdmin(String uri
) {
38 Hashtable
<String
, Object
> connEnv
= new Hashtable
<String
, Object
>();
39 connEnv
.put(Context
.INITIAL_CONTEXT_FACTORY
,
40 "com.sun.jndi.ldap.LdapCtxFactory");
41 connEnv
.put(Context
.PROVIDER_URL
, getUri().toString());
42 connEnv
.put("java.naming.ldap.attributes.binary", "userPassword");
43 // connEnv.put(Context.SECURITY_AUTHENTICATION, "simple");
44 // connEnv.put(Context.SECURITY_PRINCIPAL, "uid=admin,ou=system");
45 // connEnv.put(Context.SECURITY_CREDENTIALS, "secret");
47 initialLdapContext
= new InitialLdapContext(connEnv
, null);
48 // StartTlsResponse tls = (StartTlsResponse) ctx
49 // .extendedOperation(new StartTlsRequest());
51 initialLdapContext
.addToEnvironment(
52 Context
.SECURITY_AUTHENTICATION
, "simple");
53 initialLdapContext
.addToEnvironment(Context
.SECURITY_PRINCIPAL
,
54 "uid=admin,ou=system");
55 initialLdapContext
.addToEnvironment(Context
.SECURITY_CREDENTIALS
,
57 LdapContext ldapContext
= (LdapContext
) initialLdapContext
58 .lookup("uid=root,ou=users,dc=example,dc=com");
59 log
.debug(initialLdapContext
.getAttributes(
60 "uid=root,ou=users,dc=example,dc=com").get("cn"));
61 } catch (Exception e
) {
62 throw new ArgeoUserAdminException("Cannot connect to LDAP", e
);
66 public void destroy() {
69 initialLdapContext
.close();
70 } catch (NamingException e
) {
71 log
.error("Cannot destroy LDAP user admin", e
);
76 public Role
createRole(String name
, int type
) {
77 // TODO Auto-generated method stub
82 public boolean removeRole(String name
) {
83 // TODO Auto-generated method stub
88 public Role
getRole(String name
) {
90 Attributes attrs
= initialLdapContext
.getAttributes(name
);
92 if (attrs
.get("objectClass").contains("groupOfNames"))
93 res
= new LdifGroup(this, new LdapName(name
), attrs
);
94 else if (attrs
.get("objectClass").contains("inetOrgPerson"))
95 res
= new LdifUser(new LdapName(name
), attrs
);
97 throw new ArgeoUserAdminException("Unsupported LDAP type for "
100 } catch (NamingException e
) {
101 throw new ArgeoUserAdminException("Cannot get role for " + name
, e
);
106 public Role
[] getRoles(String filter
) throws InvalidSyntaxException
{
108 String searchFilter
= filter
;
109 if (searchFilter
== null)
110 searchFilter
= "(|(objectClass=inetOrgPerson)(objectClass=groupOfNames))";
111 SearchControls searchControls
= new SearchControls();
112 searchControls
.setSearchScope(SearchControls
.SUBTREE_SCOPE
);
114 String searchBase
= baseDn
;
115 NamingEnumeration
<SearchResult
> results
= initialLdapContext
116 .search(searchBase
, searchFilter
, searchControls
);
118 ArrayList
<Role
> res
= new ArrayList
<Role
>();
119 while (results
.hasMoreElements()) {
120 SearchResult searchResult
= results
.next();
121 Attributes attrs
= searchResult
.getAttributes();
123 if (attrs
.get("objectClass").contains("groupOfNames"))
124 role
= new LdifGroup(this, toDn(searchBase
, searchResult
),
126 else if (attrs
.get("objectClass").contains("inetOrgPerson"))
127 role
= new LdifUser(toDn(searchBase
, searchResult
), attrs
);
129 throw new ArgeoUserAdminException(
130 "Unsupported LDAP type for "
131 + searchResult
.getName());
134 return res
.toArray(new Role
[res
.size()]);
135 } catch (Exception e
) {
136 throw new ArgeoUserAdminException("Cannot get roles for filter "
142 public User
getUser(String key
, String value
) {
144 List
<User
> users
= new ArrayList
<User
>();
145 for (String prop
: getIndexedUserProperties()) {
146 User user
= getUser(prop
, value
);
150 if (users
.size() == 1)
157 String searchFilter
= "(&(objectClass=inetOrgPerson)(" + key
+ "="
160 SearchControls searchControls
= new SearchControls();
161 searchControls
.setSearchScope(SearchControls
.SUBTREE_SCOPE
);
163 String searchBase
= baseDn
;
164 NamingEnumeration
<SearchResult
> results
= initialLdapContext
165 .search(searchBase
, searchFilter
, searchControls
);
167 SearchResult searchResult
= null;
168 if (results
.hasMoreElements()) {
169 searchResult
= (SearchResult
) results
.nextElement();
170 if (results
.hasMoreElements())
173 if (searchResult
== null)
175 return new LdifUser(toDn(searchBase
, searchResult
),
176 searchResult
.getAttributes());
177 } catch (Exception e
) {
178 throw new ArgeoUserAdminException("Cannot get user with " + key
184 public Authorization
getAuthorization(User user
) {
185 LdifUser u
= (LdifUser
) user
;
186 // populateDirectMemberOf(u);
187 return new LdifAuthorization(u
, getAllRoles(u
));
190 private LdapName
toDn(String baseDn
, Binding binding
)
191 throws InvalidNameException
{
192 return new LdapName(binding
.isRelative() ? binding
.getName() + ","
193 + baseDn
: binding
.getName());
196 // void populateDirectMemberOf(LdifUser user) {
199 // String searchFilter = "(&(objectClass=groupOfNames)(member="
200 // + user.getName() + "))";
202 // SearchControls searchControls = new SearchControls();
203 // searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
205 // String searchBase = "ou=node";
206 // NamingEnumeration<SearchResult> results = initialLdapContext
207 // .search(searchBase, searchFilter, searchControls);
210 // //user.directMemberOf.clear();
211 // while (results.hasMoreElements()) {
212 // SearchResult searchResult = (SearchResult) results
214 // LdifGroup group = new LdifGroup(toDn(searchBase, searchResult),
215 // searchResult.getAttributes());
216 // populateDirectMemberOf(group);
217 // //user.directMemberOf.add(group);
219 // } catch (Exception e) {
220 // throw new ArgeoException("Cannot populate direct members of "
226 protected List
<?
extends Group
> getDirectGroups(User user
) {
227 List
<Group
> directGroups
= new ArrayList
<Group
>();
229 String searchFilter
= "(&(objectClass=groupOfNames)(member="
230 + user
.getName() + "))";
232 SearchControls searchControls
= new SearchControls();
233 searchControls
.setSearchScope(SearchControls
.SUBTREE_SCOPE
);
235 String searchBase
= getGroupsSearchBase();
236 NamingEnumeration
<SearchResult
> results
= initialLdapContext
237 .search(searchBase
, searchFilter
, searchControls
);
239 while (results
.hasMoreElements()) {
240 SearchResult searchResult
= (SearchResult
) results
242 LdifGroup group
= new LdifGroup(this, toDn(searchBase
,
243 searchResult
), searchResult
.getAttributes());
244 directGroups
.add(group
);
247 } catch (Exception e
) {
248 throw new ArgeoException("Cannot populate direct members of "
253 protected String
getGroupsSearchBase() {
254 // TODO configure group search base