]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.util/src/org/argeo/util/directory/ldap/LdapDao.java
Disable OSGi configuration admin and LDIF-based deploy config.
[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().cloneConfigProperties());
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 entryExists(LdapName dn) {
70 try {
71 return doGetEntry(dn) != null;
72 } catch (NameNotFoundException e) {
73 return false;
74 }
75 }
76
77 @Override
78 public LdapEntry doGetEntry(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 Rdn technicalRdn = LdapNameUtils.getParentRdn(name);
86 if (getDirectory().getGroupBaseRdn().equals(technicalRdn))
87 res = newGroup(name, attrs);
88 else if (getDirectory().getSystemRoleBaseRdn().equals(technicalRdn))
89 res = newGroup(name, attrs);
90 else if (getDirectory().getUserBaseRdn().equals(technicalRdn))
91 res = newUser(name, attrs);
92 else
93 res = new DefaultLdapEntry(getDirectory(), name, attrs);
94 // if (isGroup(name))
95 // res = newGroup(name, attrs);
96 // else
97 // res = newUser(name, attrs);
98 // else
99 // throw new IllegalArgumentException("Unsupported LDAP type for " + name);
100 return res;
101 } catch (NameNotFoundException e) {
102 throw e;
103 } catch (NamingException e) {
104 return null;
105 }
106 }
107
108 // protected boolean isGroup(LdapName dn) {
109 // Rdn technicalRdn = LdapNameUtils.getParentRdn(dn);
110 // if (getDirectory().getGroupBaseRdn().equals(technicalRdn)
111 // || getDirectory().getSystemRoleBaseRdn().equals(technicalRdn))
112 // return true;
113 // else if (getDirectory().getUserBaseRdn().equals(technicalRdn))
114 // return false;
115 // else
116 // throw new IllegalArgumentException(
117 // "Cannot find role type, " + technicalRdn + " is not a technical RDN for " + dn);
118 // }
119
120 @Override
121 public List<LdapEntry> doGetEntries(LdapName searchBase, String f, boolean deep) {
122 ArrayList<LdapEntry> res = new ArrayList<>();
123 try {
124 String searchFilter = f != null ? f.toString()
125 : "(|(" + objectClass + "=" + getDirectory().getUserObjectClass() + ")(" + objectClass + "="
126 + getDirectory().getGroupObjectClass() + "))";
127 SearchControls searchControls = new SearchControls();
128 // FIXME make one level consistent with deep
129 searchControls.setSearchScope(deep ? SearchControls.SUBTREE_SCOPE : SearchControls.ONELEVEL_SCOPE);
130
131 // LdapName searchBase = getBaseDn();
132 NamingEnumeration<SearchResult> results = ldapConnection.search(searchBase, searchFilter, searchControls);
133
134 results: while (results.hasMoreElements()) {
135 SearchResult searchResult = results.next();
136 Attributes attrs = searchResult.getAttributes();
137 Attribute objectClassAttr = attrs.get(objectClass.name());
138 LdapName dn = toDn(searchBase, searchResult);
139 LdapEntry role;
140 if (objectClassAttr.contains(getDirectory().getGroupObjectClass())
141 || objectClassAttr.contains(getDirectory().getGroupObjectClass().toLowerCase()))
142 role = newGroup(dn, attrs);
143 else if (objectClassAttr.contains(getDirectory().getUserObjectClass())
144 || objectClassAttr.contains(getDirectory().getUserObjectClass().toLowerCase()))
145 role = newUser(dn, attrs);
146 else {
147 // log.warn("Unsupported LDAP type for " + searchResult.getName());
148 continue results;
149 }
150 res.add(role);
151 }
152 return res;
153 } catch (AuthenticationNotSupportedException e) {
154 // ignore (typically an unsupported anonymous bind)
155 // TODO better logging
156 return res;
157 } catch (NamingException e) {
158 throw new IllegalStateException("Cannot get roles for filter " + f, e);
159 }
160 }
161
162 private LdapName toDn(LdapName baseDn, Binding binding) throws InvalidNameException {
163 return new LdapName(binding.isRelative() ? binding.getName() + "," + baseDn : binding.getName());
164 }
165
166 @Override
167 public List<LdapName> getDirectGroups(LdapName dn) {
168 List<LdapName> directGroups = new ArrayList<LdapName>();
169 try {
170 String searchFilter = "(&(" + objectClass + "=" + getDirectory().getGroupObjectClass() + ")("
171 + getDirectory().getMemberAttributeId() + "=" + dn + "))";
172
173 SearchControls searchControls = new SearchControls();
174 searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
175
176 LdapName searchBase = getDirectory().getBaseDn();
177 NamingEnumeration<SearchResult> results = ldapConnection.search(searchBase, searchFilter, searchControls);
178
179 while (results.hasMoreElements()) {
180 SearchResult searchResult = (SearchResult) results.nextElement();
181 directGroups.add(toDn(searchBase, searchResult));
182 }
183 return directGroups;
184 } catch (NamingException e) {
185 throw new IllegalStateException("Cannot populate direct members of " + dn, e);
186 }
187 }
188
189 @Override
190 public void prepare(LdapEntryWorkingCopy wc) {
191 try {
192 ldapConnection.prepareChanges(wc);
193 } catch (NamingException e) {
194 throw new IllegalStateException("Cannot prepare LDAP", e);
195 }
196 }
197
198 @Override
199 public void commit(LdapEntryWorkingCopy wc) {
200 try {
201 ldapConnection.commitChanges(wc);
202 } catch (NamingException e) {
203 throw new IllegalStateException("Cannot commit LDAP", e);
204 }
205 }
206
207 @Override
208 public void rollback(LdapEntryWorkingCopy wc) {
209 // prepare not impacting
210 }
211
212 /*
213 * HIERARCHY
214 */
215
216 @Override
217 public Iterable<HierarchyUnit> doGetDirectHierarchyUnits(LdapName searchBase, boolean functionalOnly) {
218 List<HierarchyUnit> res = new ArrayList<>();
219 try {
220 String searchFilter = "(|(" + objectClass + "=" + LdapObjs.organizationalUnit.name() + ")(" + objectClass
221 + "=" + LdapObjs.organization.name() + "))";
222 // String searchFilter = "(|(" + objectClass + "=" + LdapObjs.organizationalUnit.name() + ")(" + objectClass
223 // + "=" + LdapObjs.organization.name() + ")(cn=accounts)(cn=users)(cn=groups))";
224
225 SearchControls searchControls = new SearchControls();
226 searchControls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
227
228 NamingEnumeration<SearchResult> results = ldapConnection.search(searchBase, searchFilter, searchControls);
229
230 while (results.hasMoreElements()) {
231 SearchResult searchResult = (SearchResult) results.nextElement();
232 LdapName dn = toDn(searchBase, searchResult);
233 Attributes attrs = searchResult.getAttributes();
234 LdapHierarchyUnit hierarchyUnit = new LdapHierarchyUnit(getDirectory(), dn, attrs);
235 if (functionalOnly) {
236 if (hierarchyUnit.isFunctional())
237 res.add(hierarchyUnit);
238 } else {
239 res.add(hierarchyUnit);
240 }
241 }
242 return res;
243 } catch (NamingException e) {
244 throw new IllegalStateException("Cannot get direct hierarchy units ", e);
245 }
246 }
247
248 @Override
249 public HierarchyUnit doGetHierarchyUnit(LdapName dn) {
250 try {
251 if (getDirectory().getBaseDn().equals(dn))
252 return getDirectory();
253 if (!dn.startsWith(getDirectory().getBaseDn()))
254 throw new IllegalArgumentException(dn + " does not start with base DN " + getDirectory().getBaseDn());
255 Attributes attrs = ldapConnection.getAttributes(dn);
256 return new LdapHierarchyUnit(getDirectory(), dn, attrs);
257 } catch (NamingException e) {
258 throw new IllegalStateException("Cannot get hierarchy unit " + dn, e);
259 }
260 }
261
262 }