]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.security.core/src/org/argeo/osgi/useradmin/LdapUserAdmin.java
Node registration
[lgpl/argeo-commons.git] / org.argeo.security.core / src / org / argeo / osgi / useradmin / LdapUserAdmin.java
1 package org.argeo.osgi.useradmin;
2
3 import static org.argeo.osgi.useradmin.LdifName.objectClass;
4
5 import java.util.ArrayList;
6 import java.util.Dictionary;
7 import java.util.Hashtable;
8 import java.util.List;
9
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;
21
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;
27
28 public class LdapUserAdmin extends AbstractUserDirectory {
29 private final static Log log = LogFactory.getLog(LdapUserAdmin.class);
30
31 private InitialLdapContext initialLdapContext = null;
32
33 public LdapUserAdmin(Dictionary<String, ?> properties) {
34 super(properties);
35 try {
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());
42
43 initialLdapContext = new InitialLdapContext(connEnv, null);
44 // StartTlsResponse tls = (StartTlsResponse) ctx
45 // .extendedOperation(new StartTlsRequest());
46 // tls.negotiate();
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);
54 if (creds != null) {
55 initialLdapContext.addToEnvironment(
56 Context.SECURITY_CREDENTIALS, creds.toString());
57
58 }
59 }
60 // initialLdapContext.addToEnvironment(Context.SECURITY_PRINCIPAL,
61 // "uid=admin,ou=system");
62 // initialLdapContext.addToEnvironment(Context.SECURITY_CREDENTIALS,
63 // "secret");
64 } catch (Exception e) {
65 throw new UserDirectoryException("Cannot connect to LDAP", e);
66 }
67 }
68
69 public void destroy() {
70 try {
71 // tls.close();
72 initialLdapContext.close();
73 } catch (NamingException e) {
74 log.error("Cannot destroy LDAP user admin", e);
75 }
76 }
77
78 protected InitialLdapContext getLdapContext() {
79 return initialLdapContext;
80 }
81
82 @Override
83 protected Boolean daoHasRole(LdapName dn) {
84 return daoGetRole(dn) != null;
85 }
86
87 @Override
88 protected DirectoryUser daoGetRole(LdapName name) {
89 try {
90 Attributes attrs = getLdapContext().getAttributes(name);
91 if (attrs.size() == 0)
92 return null;
93 LdifUser res;
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);
99 else
100 throw new UserDirectoryException("Unsupported LDAP type for "
101 + name);
102 return res;
103 } catch (NamingException e) {
104 throw new UserDirectoryException("Cannot get role for " + name, e);
105 }
106 }
107
108 @Override
109 protected List<DirectoryUser> doGetRoles(Filter f) {
110 // TODO Auto-generated method stub
111 try {
112 String searchFilter = f != null ? f.toString() : "(|("
113 + objectClass + "=" + getUserObjectClass() + ")("
114 + objectClass + "=" + getGroupObjectClass() + "))";
115 SearchControls searchControls = new SearchControls();
116 searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
117
118 String searchBase = getBaseDn();
119 NamingEnumeration<SearchResult> results = getLdapContext().search(
120 searchBase, searchFilter, searchControls);
121
122 ArrayList<DirectoryUser> res = new ArrayList<DirectoryUser>();
123 while (results.hasMoreElements()) {
124 SearchResult searchResult = results.next();
125 Attributes attrs = searchResult.getAttributes();
126 LdifUser role;
127 if (attrs.get(objectClass.name()).contains(
128 getGroupObjectClass()))
129 role = new LdifGroup(this, toDn(searchBase, searchResult),
130 attrs);
131 else if (attrs.get(objectClass.name()).contains(
132 getUserObjectClass()))
133 role = new LdifUser(this, toDn(searchBase, searchResult),
134 attrs);
135 else
136 throw new UserDirectoryException(
137 "Unsupported LDAP type for "
138 + searchResult.getName());
139 res.add(role);
140 }
141 return res;
142 } catch (Exception e) {
143 throw new UserDirectoryException(
144 "Cannot get roles for filter " + f, e);
145 }
146 }
147
148 @Override
149 protected void doGetUser(String key, String value,
150 List<DirectoryUser> collectedUsers) {
151 try {
152 String searchFilter = "(&(" + objectClass + "="
153 + getUserObjectClass() + ")(" + key + "=" + value + "))";
154
155 SearchControls searchControls = new SearchControls();
156 searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
157
158 String searchBase = getBaseDn();
159 NamingEnumeration<SearchResult> results = getLdapContext().search(
160 searchBase, searchFilter, searchControls);
161
162 SearchResult searchResult = null;
163 if (results.hasMoreElements()) {
164 searchResult = (SearchResult) results.nextElement();
165 if (results.hasMoreElements())
166 searchResult = null;
167 }
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
173 + "=" + value, e);
174 }
175
176 }
177
178 private LdapName toDn(String baseDn, Binding binding)
179 throws InvalidNameException {
180 return new LdapName(binding.isRelative() ? binding.getName() + ","
181 + baseDn : binding.getName());
182 }
183
184 @Override
185 protected List<DirectoryGroup> getDirectGroups(User user) {
186 List<DirectoryGroup> directGroups = new ArrayList<DirectoryGroup>();
187 try {
188 String searchFilter = "(&(" + objectClass + "="
189 + getGroupObjectClass() + ")(" + getMemberAttributeId()
190 + "=" + user.getName() + "))";
191
192 SearchControls searchControls = new SearchControls();
193 searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
194
195 String searchBase = getBaseDn();
196 NamingEnumeration<SearchResult> results = getLdapContext().search(
197 searchBase, searchFilter, searchControls);
198
199 while (results.hasMoreElements()) {
200 SearchResult searchResult = (SearchResult) results
201 .nextElement();
202 LdifGroup group = new LdifGroup(this, toDn(searchBase,
203 searchResult), searchResult.getAttributes());
204 directGroups.add(group);
205 }
206 return directGroups;
207 } catch (Exception e) {
208 throw new ArgeoException("Cannot populate direct members of "
209 + user, e);
210 }
211 }
212
213 @Override
214 protected void prepare(WorkingCopy wc) {
215 try {
216 getLdapContext().reconnect(getLdapContext().getConnectControls());
217 // delete
218 for (LdapName dn : wc.getDeletedUsers().keySet()) {
219 if (!entryExists(dn))
220 throw new UserDirectoryException("User to delete no found "
221 + dn);
222 }
223 // add
224 for (LdapName dn : wc.getNewUsers().keySet()) {
225 if (!entryExists(dn))
226 throw new UserDirectoryException("User to create found "
227 + dn);
228 }
229 // modify
230 for (LdapName dn : wc.getModifiedUsers().keySet()) {
231 if (!entryExists(dn))
232 throw new UserDirectoryException("User to modify no found "
233 + dn);
234 }
235 } catch (NamingException e) {
236 throw new UserDirectoryException("Cannot prepare LDAP", e);
237 }
238 }
239
240 private boolean entryExists(LdapName dn) throws NamingException {
241 return getLdapContext().getAttributes(dn).size() != 0;
242 }
243
244 @Override
245 protected void commit(WorkingCopy wc) {
246 try {
247 // delete
248 for (LdapName dn : wc.getDeletedUsers().keySet()) {
249 getLdapContext().destroySubcontext(dn);
250 }
251 // add
252 for (LdapName dn : wc.getNewUsers().keySet()) {
253 DirectoryUser user = wc.getNewUsers().get(dn);
254 getLdapContext().createSubcontext(dn, user.getAttributes());
255 }
256 // modify
257 for (LdapName dn : wc.getModifiedUsers().keySet()) {
258 Attributes modifiedAttrs = wc.getModifiedUsers().get(dn);
259 getLdapContext().modifyAttributes(dn,
260 DirContext.REPLACE_ATTRIBUTE, modifiedAttrs);
261 }
262 } catch (NamingException e) {
263 throw new UserDirectoryException("Cannot commit LDAP", e);
264 }
265 }
266
267 @Override
268 protected void rollback(WorkingCopy wc) {
269 // prepare not impacting
270 }
271
272 }