]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.util/src/org/argeo/util/directory/ldap/LdapDao.java
Separate LDIF and LDAP DAOs
[lgpl/argeo-commons.git] / org.argeo.util / src / org / argeo / util / directory / ldap / LdapDao.java
1 package org.argeo.util.directory.ldap;
2
3 import static org.argeo.util.naming.LdapAttrs.objectClass;
4
5 import java.util.ArrayList;
6 import java.util.List;
7
8 import javax.naming.AuthenticationNotSupportedException;
9 import javax.naming.Binding;
10 import javax.naming.InvalidNameException;
11 import javax.naming.NameNotFoundException;
12 import javax.naming.NamingEnumeration;
13 import javax.naming.NamingException;
14 import javax.naming.directory.Attribute;
15 import javax.naming.directory.Attributes;
16 import javax.naming.directory.SearchControls;
17 import javax.naming.directory.SearchResult;
18 import javax.naming.ldap.LdapName;
19 import javax.naming.ldap.Rdn;
20
21 import org.argeo.util.directory.HierarchyUnit;
22 import org.argeo.util.naming.LdapObjs;
23
24 /** A user admin based on a LDAP server. */
25 public class LdapDao extends AbstractLdapDirectoryDao {
26 private LdapConnection ldapConnection;
27
28 // public LdapUserAdmin(Dictionary<String, ?> properties) {
29 // this(properties, false);
30 // }
31
32 public LdapDao(AbstractLdapDirectory directory) {
33 super(directory);
34 }
35
36 @Override
37 public void init() {
38 ldapConnection = new LdapConnection(getDirectory().getUri().toString(), getDirectory().getProperties());
39 }
40
41 public void destroy() {
42 ldapConnection.destroy();
43 }
44
45 // @Override
46 // protected AbstractUserDirectory scope(User user) {
47 // Dictionary<String, Object> credentials = user.getCredentials();
48 // String username = (String) credentials.get(SHARED_STATE_USERNAME);
49 // if (username == null)
50 // username = user.getName();
51 // Dictionary<String, Object> properties = cloneProperties();
52 // properties.put(Context.SECURITY_PRINCIPAL, username.toString());
53 // Object pwdCred = credentials.get(SHARED_STATE_PASSWORD);
54 // byte[] pwd = (byte[]) pwdCred;
55 // if (pwd != null) {
56 // char[] password = DirectoryDigestUtils.bytesToChars(pwd);
57 // properties.put(Context.SECURITY_CREDENTIALS, new String(password));
58 // } else {
59 // properties.put(Context.SECURITY_AUTHENTICATION, "GSSAPI");
60 // }
61 // return new LdapUserAdmin(properties, true);
62 // }
63
64 // protected InitialLdapContext getLdapContext() {
65 // return initialLdapContext;
66 // }
67
68 @Override
69 public Boolean daoHasEntry(LdapName dn) {
70 try {
71 return daoGetEntry(dn) != null;
72 } catch (NameNotFoundException e) {
73 return false;
74 }
75 }
76
77 @Override
78 public LdapEntry daoGetEntry(LdapName name) throws NameNotFoundException {
79 try {
80 Attributes attrs = ldapConnection.getAttributes(name);
81 if (attrs.size() == 0)
82 return null;
83 // int roleType = roleType(name);
84 LdapEntry res;
85 if (isGroup(name))
86 res = newGroup(name, attrs);
87 else
88 res = newUser(name, attrs);
89 // else
90 // throw new IllegalArgumentException("Unsupported LDAP type for " + name);
91 return res;
92 } catch (NameNotFoundException e) {
93 throw e;
94 } catch (NamingException e) {
95 return null;
96 }
97 }
98
99 protected boolean isGroup(LdapName dn) {
100 Rdn technicalRdn = LdapNameUtils.getParentRdn(dn);
101 if (getDirectory().getGroupBaseRdn().equals(technicalRdn)
102 || getDirectory().getSystemRoleBaseRdn().equals(technicalRdn))
103 return true;
104 else if (getDirectory().getUserBaseRdn().equals(technicalRdn))
105 return false;
106 else
107 throw new IllegalArgumentException(
108 "Cannot dind role type, " + technicalRdn + " is not a technical RDN for " + dn);
109 }
110
111 @Override
112 public List<LdapEntry> doGetEntries(LdapName searchBase, String f, boolean deep) {
113 ArrayList<LdapEntry> res = new ArrayList<>();
114 try {
115 String searchFilter = f != null ? f.toString()
116 : "(|(" + objectClass + "=" + getDirectory().getUserObjectClass() + ")(" + objectClass + "="
117 + getDirectory().getGroupObjectClass() + "))";
118 SearchControls searchControls = new SearchControls();
119 // FIXME make one level consistent with deep
120 searchControls.setSearchScope(deep ? SearchControls.SUBTREE_SCOPE : SearchControls.ONELEVEL_SCOPE);
121
122 // LdapName searchBase = getBaseDn();
123 NamingEnumeration<SearchResult> results = ldapConnection.search(searchBase, searchFilter, searchControls);
124
125 results: while (results.hasMoreElements()) {
126 SearchResult searchResult = results.next();
127 Attributes attrs = searchResult.getAttributes();
128 Attribute objectClassAttr = attrs.get(objectClass.name());
129 LdapName dn = toDn(searchBase, searchResult);
130 LdapEntry role;
131 if (objectClassAttr.contains(getDirectory().getGroupObjectClass())
132 || objectClassAttr.contains(getDirectory().getGroupObjectClass().toLowerCase()))
133 role = newGroup(dn, attrs);
134 else if (objectClassAttr.contains(getDirectory().getUserObjectClass())
135 || objectClassAttr.contains(getDirectory().getUserObjectClass().toLowerCase()))
136 role = newUser(dn, attrs);
137 else {
138 // log.warn("Unsupported LDAP type for " + searchResult.getName());
139 continue results;
140 }
141 res.add(role);
142 }
143 return res;
144 } catch (AuthenticationNotSupportedException e) {
145 // ignore (typically an unsupported anonymous bind)
146 // TODO better logging
147 return res;
148 } catch (NamingException e) {
149 throw new IllegalStateException("Cannot get roles for filter " + f, e);
150 }
151 }
152
153 private LdapName toDn(LdapName baseDn, Binding binding) throws InvalidNameException {
154 return new LdapName(binding.isRelative() ? binding.getName() + "," + baseDn : binding.getName());
155 }
156
157 @Override
158 public List<LdapName> getDirectGroups(LdapName dn) {
159 List<LdapName> directGroups = new ArrayList<LdapName>();
160 try {
161 String searchFilter = "(&(" + objectClass + "=" + getDirectory().getGroupObjectClass() + ")("
162 + getDirectory().getMemberAttributeId() + "=" + dn + "))";
163
164 SearchControls searchControls = new SearchControls();
165 searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
166
167 LdapName searchBase = getDirectory().getBaseDn();
168 NamingEnumeration<SearchResult> results = ldapConnection.search(searchBase, searchFilter, searchControls);
169
170 while (results.hasMoreElements()) {
171 SearchResult searchResult = (SearchResult) results.nextElement();
172 directGroups.add(toDn(searchBase, searchResult));
173 }
174 return directGroups;
175 } catch (NamingException e) {
176 throw new IllegalStateException("Cannot populate direct members of " + dn, e);
177 }
178 }
179
180 @Override
181 public void prepare(LdapEntryWorkingCopy wc) {
182 try {
183 ldapConnection.prepareChanges(wc);
184 } catch (NamingException e) {
185 throw new IllegalStateException("Cannot prepare LDAP", e);
186 }
187 }
188
189 @Override
190 public void commit(LdapEntryWorkingCopy wc) {
191 try {
192 ldapConnection.commitChanges(wc);
193 } catch (NamingException e) {
194 throw new IllegalStateException("Cannot commit LDAP", e);
195 }
196 }
197
198 @Override
199 public void rollback(LdapEntryWorkingCopy wc) {
200 // prepare not impacting
201 }
202
203 /*
204 * HIERARCHY
205 */
206
207 @Override
208 public Iterable<HierarchyUnit> doGetDirectHierarchyUnits(LdapName searchBase, boolean functionalOnly) {
209 List<HierarchyUnit> res = new ArrayList<>();
210 try {
211 String searchFilter = "(|(" + objectClass + "=" + LdapObjs.organizationalUnit.name() + ")(" + objectClass
212 + "=" + LdapObjs.organization.name() + "))";
213
214 SearchControls searchControls = new SearchControls();
215 searchControls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
216
217 NamingEnumeration<SearchResult> results = ldapConnection.search(searchBase, searchFilter, searchControls);
218
219 while (results.hasMoreElements()) {
220 SearchResult searchResult = (SearchResult) results.nextElement();
221 LdapName dn = toDn(searchBase, searchResult);
222 Attributes attrs = searchResult.getAttributes();
223 LdapHierarchyUnit hierarchyUnit = new LdapHierarchyUnit(getDirectory(), dn, attrs);
224 if (functionalOnly) {
225 if (hierarchyUnit.isFunctional())
226 res.add(hierarchyUnit);
227 } else {
228 res.add(hierarchyUnit);
229 }
230 }
231 return res;
232 } catch (NamingException e) {
233 throw new IllegalStateException("Cannot get direct hierarchy units ", e);
234 }
235 }
236
237 @Override
238 public HierarchyUnit doGetHierarchyUnit(LdapName dn) {
239 try {
240 Attributes attrs = ldapConnection.getAttributes(dn);
241 return new LdapHierarchyUnit(getDirectory(), dn, attrs);
242 } catch (NamingException e) {
243 throw new IllegalStateException("Cannot get hierarchy unit " + dn, e);
244 }
245 }
246
247 }