]> git.argeo.org Git - lgpl/argeo-commons.git/blob - useradmin/LdapUserAdmin.java
Prepare next development cycle
[lgpl/argeo-commons.git] / useradmin / LdapUserAdmin.java
1 package org.argeo.osgi.useradmin;
2
3 import static org.argeo.util.naming.LdapAttrs.objectClass;
4
5 import java.util.ArrayList;
6 import java.util.Dictionary;
7 import java.util.List;
8
9 import javax.naming.AuthenticationNotSupportedException;
10 import javax.naming.Binding;
11 import javax.naming.Context;
12 import javax.naming.InvalidNameException;
13 import javax.naming.NameNotFoundException;
14 import javax.naming.NamingEnumeration;
15 import javax.naming.NamingException;
16 import javax.naming.directory.Attribute;
17 import javax.naming.directory.Attributes;
18 import javax.naming.directory.SearchControls;
19 import javax.naming.directory.SearchResult;
20 import javax.naming.ldap.LdapName;
21
22 import org.osgi.framework.Filter;
23 import org.osgi.service.useradmin.Role;
24 import org.osgi.service.useradmin.User;
25
26 /** A user admin based on a LDAP server. */
27 public class LdapUserAdmin extends AbstractUserDirectory {
28 private LdapConnection ldapConnection;
29
30 public LdapUserAdmin(Dictionary<String, ?> properties) {
31 this(properties, false);
32 }
33
34 public LdapUserAdmin(Dictionary<String, ?> properties, boolean scoped) {
35 super(null, properties, scoped);
36 ldapConnection = new LdapConnection(getUri().toString(), properties);
37 }
38
39 public void destroy() {
40 ldapConnection.destroy();
41 }
42
43 @Override
44 protected AbstractUserDirectory scope(User user) {
45 Dictionary<String, Object> credentials = user.getCredentials();
46 String username = (String) credentials.get(SHARED_STATE_USERNAME);
47 if (username == null)
48 username = user.getName();
49 Dictionary<String, Object> properties = cloneProperties();
50 properties.put(Context.SECURITY_PRINCIPAL, username.toString());
51 Object pwdCred = credentials.get(SHARED_STATE_PASSWORD);
52 byte[] pwd = (byte[]) pwdCred;
53 if (pwd != null) {
54 char[] password = DigestUtils.bytesToChars(pwd);
55 properties.put(Context.SECURITY_CREDENTIALS, new String(password));
56 } else {
57 properties.put(Context.SECURITY_AUTHENTICATION, "GSSAPI");
58 }
59 return new LdapUserAdmin(properties, true);
60 }
61
62 // protected InitialLdapContext getLdapContext() {
63 // return initialLdapContext;
64 // }
65
66 @Override
67 protected Boolean daoHasRole(LdapName dn) {
68 try {
69 return daoGetRole(dn) != null;
70 } catch (NameNotFoundException e) {
71 return false;
72 }
73 }
74
75 @Override
76 protected DirectoryUser daoGetRole(LdapName name) throws NameNotFoundException {
77 try {
78 Attributes attrs = ldapConnection.getAttributes(name);
79 if (attrs.size() == 0)
80 return null;
81 int roleType = roleType(name);
82 LdifUser res;
83 if (roleType == Role.GROUP)
84 res = new LdifGroup(this, name, attrs);
85 else if (roleType == Role.USER)
86 res = new LdifUser(this, name, attrs);
87 else
88 throw new UserDirectoryException("Unsupported LDAP type for " + name);
89 return res;
90 } catch (NameNotFoundException e) {
91 throw e;
92 } catch (NamingException e) {
93 return null;
94 }
95 }
96
97 @Override
98 protected List<DirectoryUser> doGetRoles(LdapName searchBase, Filter f, boolean deep) {
99 ArrayList<DirectoryUser> res = new ArrayList<DirectoryUser>();
100 try {
101 String searchFilter = f != null ? f.toString()
102 : "(|(" + objectClass + "=" + getUserObjectClass() + ")(" + objectClass + "="
103 + getGroupObjectClass() + "))";
104 SearchControls searchControls = new SearchControls();
105 // FIXME make one level consistent with deep
106 searchControls.setSearchScope(deep ? SearchControls.SUBTREE_SCOPE : SearchControls.ONELEVEL_SCOPE);
107
108 // LdapName searchBase = getBaseDn();
109 NamingEnumeration<SearchResult> results = ldapConnection.search(searchBase, searchFilter, searchControls);
110
111 results: while (results.hasMoreElements()) {
112 SearchResult searchResult = results.next();
113 Attributes attrs = searchResult.getAttributes();
114 Attribute objectClassAttr = attrs.get(objectClass.name());
115 LdapName dn = toDn(searchBase, searchResult);
116 LdifUser role;
117 if (objectClassAttr.contains(getGroupObjectClass())
118 || objectClassAttr.contains(getGroupObjectClass().toLowerCase()))
119 role = new LdifGroup(this, dn, attrs);
120 else if (objectClassAttr.contains(getUserObjectClass())
121 || objectClassAttr.contains(getUserObjectClass().toLowerCase()))
122 role = new LdifUser(this, dn, attrs);
123 else {
124 // log.warn("Unsupported LDAP type for " + searchResult.getName());
125 continue results;
126 }
127 res.add(role);
128 }
129 return res;
130 } catch (AuthenticationNotSupportedException e) {
131 // ignore (typically an unsupported anonymous bind)
132 // TODO better logging
133 return res;
134 } catch (Exception e) {
135 e.printStackTrace();
136 throw new UserDirectoryException("Cannot get roles for filter " + f, e);
137 }
138 }
139
140 private LdapName toDn(LdapName baseDn, Binding binding) throws InvalidNameException {
141 return new LdapName(binding.isRelative() ? binding.getName() + "," + baseDn : binding.getName());
142 }
143
144 @Override
145 protected List<LdapName> getDirectGroups(LdapName dn) {
146 List<LdapName> directGroups = new ArrayList<LdapName>();
147 try {
148 String searchFilter = "(&(" + objectClass + "=" + getGroupObjectClass() + ")(" + getMemberAttributeId()
149 + "=" + dn + "))";
150
151 SearchControls searchControls = new SearchControls();
152 searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
153
154 LdapName searchBase = getBaseDn();
155 NamingEnumeration<SearchResult> results = ldapConnection.search(searchBase, searchFilter, searchControls);
156
157 while (results.hasMoreElements()) {
158 SearchResult searchResult = (SearchResult) results.nextElement();
159 directGroups.add(toDn(searchBase, searchResult));
160 }
161 return directGroups;
162 } catch (Exception e) {
163 throw new UserDirectoryException("Cannot populate direct members of " + dn, e);
164 }
165 }
166
167 @Override
168 protected void prepare(UserDirectoryWorkingCopy wc) {
169 try {
170 ldapConnection.prepareChanges(wc);
171 } catch (NamingException e) {
172 throw new UserDirectoryException("Cannot prepare LDAP", e);
173 }
174 }
175
176 @Override
177 protected void commit(UserDirectoryWorkingCopy wc) {
178 try {
179 ldapConnection.commitChanges(wc);
180 } catch (NamingException e) {
181 throw new UserDirectoryException("Cannot commit LDAP", e);
182 }
183 }
184
185 @Override
186 protected void rollback(UserDirectoryWorkingCopy wc) {
187 // prepare not impacting
188 }
189
190 // @Override
191 // public HierarchyUnit getHierarchyUnit(String path) {
192 // LdapName dn = LdapNameUtils.toLdapName(path);
193 // Attributes attrs = ldapConnection.getAttributes(dn);
194 //
195 // }
196
197 }