View Javadoc

1   /*
2   * Licensed to the Apache Software Foundation (ASF) under one or more
3   * contributor license agreements.  See the NOTICE file distributed with
4   * this work for additional information regarding copyright ownership.
5   * The ASF licenses this file to You under the Apache License, Version 2.0
6   * (the "License"); you may not use this file except in compliance with
7   * the License.  You may obtain a copy of the License at
8   *
9   *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17  package org.apache.jetspeed.security.spi.impl.ldap;
18  
19  import java.security.Principal;
20  import java.util.ArrayList;
21  import java.util.Enumeration;
22  import java.util.Iterator;
23  import java.util.List;
24  
25  import javax.naming.NamingEnumeration;
26  import javax.naming.NamingException;
27  import javax.naming.directory.Attribute;
28  import javax.naming.directory.Attributes;
29  import javax.naming.directory.BasicAttribute;
30  import javax.naming.directory.BasicAttributes;
31  import javax.naming.directory.DirContext;
32  import javax.naming.directory.SearchControls;
33  import javax.naming.directory.SearchResult;
34  
35  import org.apache.commons.lang.StringUtils;
36  import org.apache.commons.logging.Log;
37  import org.apache.commons.logging.LogFactory;
38  import org.apache.jetspeed.security.SecurityException;
39  import org.apache.jetspeed.security.impl.UserPrincipalImpl;
40  
41  
42  public class LdapMemberShipDaoImpl extends LdapPrincipalDaoImpl implements LdapMembershipDao {
43  
44  	/*** The logger. */
45  	private static final Log logger = LogFactory.getLog(LdapMemberShipDaoImpl.class);
46  
47  	public LdapMemberShipDaoImpl() throws SecurityException {
48  		super();
49  	}
50  	
51  	public LdapMemberShipDaoImpl(LdapBindingConfig config) throws SecurityException {
52  		super(config);
53  	}	
54  
55  	/* (non-Javadoc)
56  	 * @see org.apache.jetspeed.security.spi.impl.ldap.LdapMembershipDao#searchGroupMemberShipByGroup(java.lang.String, javax.naming.directory.SearchControls)
57  	 */
58  	public String[] searchGroupMemberShipByGroup(final String userPrincipalUid, SearchControls cons) throws NamingException {
59  		
60  		String query = "(&(" + getGroupMembershipAttribute() + "=" + getUserDN(userPrincipalUid) + ")" + getGroupFilter()  + ")";
61  		
62  	    if (logger.isDebugEnabled())
63  	    {
64  	        logger.debug("query[" + query + "]");
65  	    }
66  	    
67  	    cons.setSearchScope(getSearchScope());
68          String groupFilterBase = getGroupFilterBase();
69  	    NamingEnumeration searchResults = ((DirContext) ctx).search(groupFilterBase,query , cons);	    
70  
71  	   List groupPrincipalUids = new ArrayList();
72  	    while (searchResults.hasMore())
73  	    {
74  	        SearchResult result = (SearchResult) searchResults.next();
75  	        Attributes answer = result.getAttributes();
76  	        groupPrincipalUids.addAll(getAttributes(getAttribute(getGroupIdAttribute(), answer)));
77  	    }
78  	    return (String[]) groupPrincipalUids.toArray(new String[groupPrincipalUids.size()]);
79  	
80  	}
81  
82  	/* (non-Javadoc)
83  	 * @see org.apache.jetspeed.security.spi.impl.ldap.LdapMembershipDao#searchGroupMemberShipByUser(java.lang.String, javax.naming.directory.SearchControls)
84  	 */
85  	public String[] searchGroupMemberShipByUser(final String userPrincipalUid, SearchControls cons) throws NamingException {
86  		NamingEnumeration searchResults = searchByWildcardedUid(userPrincipalUid, cons);
87  	    
88  	    if (!searchResults.hasMore())
89  	    {
90  	        throw new NamingException("Could not find any user with uid[" + userPrincipalUid + "]");
91  	    }
92  	    
93  		Attributes userAttributes = getFirstUser(searchResults);
94  		List groupUids = new ArrayList();
95  		Attribute attr = getAttribute(getUserGroupMembershipAttribute(), userAttributes);
96  		 List attrs = getAttributes(attr);
97  		        Iterator it = attrs.iterator();
98  		        while(it.hasNext()) {
99  		        	String cnfull = (String)it.next();
100 		        	if(cnfull.toLowerCase().indexOf(getGroupFilterBase().toLowerCase())!=-1) {
101 			        	String cn = extractLdapAttr(cnfull,getRoleUidAttribute());
102 			        	if (cn != null){
103 			        		groupUids.add(cn);
104 			        	}
105 		        	}
106 		        }
107 	    //List uids = getAttributes(getAttribute(getUserGroupMembershipAttribute(), userAttributes),getGroupFilterBase());
108 	    return (String[]) groupUids.toArray(new String[groupUids.size()]);
109 	}
110 
111 	/* (non-Javadoc)
112 	 * @see org.apache.jetspeed.security.spi.impl.ldap.LdapMembershipDao#searchRoleMemberShipByRole(java.lang.String, javax.naming.directory.SearchControls)
113 	 */
114 	public String[] searchRoleMemberShipByRole(final String userPrincipalUid, SearchControls cons) throws NamingException {
115 
116 		String query = "(&(" + getRoleMembershipAttribute() + "=" + getUserDN(userPrincipalUid) + ")" + getRoleFilter()  + ")";
117 		
118 	    if (logger.isDebugEnabled())
119 	    {
120 	        logger.debug("query[" + query + "]");
121 	    }
122 
123 	    cons.setSearchScope(getSearchScope());
124 	    NamingEnumeration searchResults = ((DirContext) ctx).search(getRoleFilterBase(),query , cons);
125 	    List rolePrincipalUids = new ArrayList();
126 	     while (searchResults.hasMore())
127 	     {
128 	    	 
129 	         SearchResult result = (SearchResult) searchResults.next();
130 	         Attributes answer = result.getAttributes();
131 	         rolePrincipalUids.addAll(getAttributes(getAttribute(getRoleIdAttribute(), answer)));
132 	     }
133 	     return (String[]) rolePrincipalUids.toArray(new String[rolePrincipalUids.size()]);
134 	}
135 
136 	/* (non-Javadoc)
137 	 * @see org.apache.jetspeed.security.spi.impl.ldap.LdapMembershipDao#searchRoleMemberShipByUser(java.lang.String, javax.naming.directory.SearchControls)
138 	 */
139 	public String[] searchRoleMemberShipByUser(final String userPrincipalUid, SearchControls cons) throws NamingException {
140 	
141 		NamingEnumeration results = searchByWildcardedUid(userPrincipalUid, cons);
142 	
143 		if (!results.hasMore())
144 		{
145 		    throw new NamingException("Could not find any user with uid[" + userPrincipalUid + "]");
146 		}
147 		
148 		Attributes userAttributes = getFirstUser(results);
149 		List newAttrs = new ArrayList();
150 		Attribute attr = getAttribute(getUserRoleMembershipAttribute(), userAttributes);
151 		 List attrs = getAttributes(attr);
152 		        Iterator it = attrs.iterator();
153 		        while(it.hasNext()) {
154 		        	String cnfull = (String)it.next();
155 		        	if(cnfull.toLowerCase().indexOf(getRoleFilterBase().toLowerCase())!=-1) {
156 			        	String cn = extractLdapAttr(cnfull,getRoleUidAttribute());
157 			        	if (cn != null){
158 			        		newAttrs.add(cn);
159 			        	}
160 		        	}else{
161 		        		// No conversion required (I think!)
162 		        		String cn = cnfull;
163 		        		newAttrs.add(cn);
164 		        	}
165 		        }
166 		return (String[]) newAttrs.toArray(new String[newAttrs.size()]);
167 	}
168 
169 	/* (non-Javadoc)
170 	 * @see org.apache.jetspeed.security.spi.impl.ldap.LdapMembershipDao#searchUsersFromGroupByGroup(java.lang.String, javax.naming.directory.SearchControls)
171 	 */
172 	public String[] searchUsersFromGroupByGroup(final String groupPrincipalUid, SearchControls cons)
173 	        throws NamingException
174 	{
175 	
176 		String query = "(&(" + getGroupIdAttribute() + "=" + (groupPrincipalUid) + ")" + getGroupFilter() + ")";
177 	    
178 		if (logger.isDebugEnabled())
179 	    {
180 	        logger.debug("query[" + query + "]");
181 	    }
182 	    
183 	    ArrayList userPrincipalUids=new ArrayList();
184 	    
185 	    cons.setSearchScope(getSearchScope());
186 	    NamingEnumeration results = ((DirContext) ctx).search(getGroupFilterBase(),query , cons);	    
187 		
188 	    while (results.hasMore())
189 	    {
190 	        SearchResult result = (SearchResult) results.next();
191 	        Attributes answer = result.getAttributes();
192 	        
193 	        List newAttrs = new ArrayList();
194 	        
195 	        Attribute userPrincipalUid = getAttribute(getGroupMembershipAttribute(), answer);
196 	        List attrs = getAttributes(userPrincipalUid);
197 	        Iterator it = attrs.iterator();
198 	        while(it.hasNext()) {
199 	        	String uidfull = (String)it.next();
200 	        	if (!StringUtils.isEmpty(uidfull)) {
201 		        	if (uidfull.toLowerCase().indexOf(getUserFilterBase().toLowerCase())!=-1) {
202 			        	String uid = extractLdapAttr(uidfull,getUserIdAttribute());
203 		        		if (uid != null){
204 				        	newAttrs.add(uid);
205 		        		}
206 		        	}
207 	        	}
208 	        }
209 	        userPrincipalUids.addAll(newAttrs);
210 	    }
211 	    return (String[]) userPrincipalUids.toArray(new String[userPrincipalUids.size()]);
212 	}
213 
214 	/* (non-Javadoc)
215 	 * @see org.apache.jetspeed.security.spi.impl.ldap.LdapMembershipDao#searchUsersFromGroupByUser(java.lang.String, javax.naming.directory.SearchControls)
216 	 */
217 	public String[] searchUsersFromGroupByUser(final String groupPrincipalUid, SearchControls cons)
218 	        throws NamingException
219 	{
220 		
221 		String query = "(&(" + getUserGroupMembershipAttribute() + "=" + getGroupDN(groupPrincipalUid) + ")" + getUserFilter() + ")";
222 	    if (logger.isDebugEnabled())
223 	    {
224 	        logger.debug("query[" + query + "]");
225 	    }
226 
227 	    cons.setSearchScope(getSearchScope());
228 	    NamingEnumeration results = ((DirContext) ctx).search(getUserFilterBase(),query , cons);	    
229 
230 	    ArrayList userPrincipalUids = new ArrayList();
231 	    
232 	    while (results.hasMore())
233 	    {
234 	        SearchResult result = (SearchResult) results.next();
235 	        Attributes answer = result.getAttributes();
236 	        userPrincipalUids.addAll(getAttributes(getAttribute(getUserIdAttribute(), answer)));
237 	    }
238 	    return (String[]) userPrincipalUids.toArray(new String[userPrincipalUids.size()]);
239 	}
240 	
241 	public String[] searchRolesFromGroupByGroup(final String groupPrincipalUid,
242 			SearchControls cons) throws NamingException {
243 
244 		String query = "(&(" + getGroupIdAttribute() + "=" + (groupPrincipalUid) + ")" + getGroupFilter() + ")";
245 
246 		if (logger.isDebugEnabled()) {
247 			logger.debug("query[" + query + "]");
248 		}
249 
250 		ArrayList rolePrincipalUids = new ArrayList();
251 
252 	    cons.setSearchScope(getSearchScope());
253 	    NamingEnumeration groups = ((DirContext) ctx).search(getGroupFilterBase(),query , cons);	    
254 
255 		while (groups.hasMore()) {
256 			SearchResult group = (SearchResult) groups.next();
257 			Attributes groupAttributes = group.getAttributes();
258 
259 			Attribute rolesFromGroup = getAttribute(getGroupMembershipForRoleAttribute(), groupAttributes);
260 			List roleDNs = getAttributes(rolesFromGroup,getRoleFilterBase());
261 			Iterator it = roleDNs.iterator();
262 			while (it.hasNext()) {
263 				String roleDN = (String) it.next();
264 				if (!StringUtils.isEmpty(roleDN)) {
265 					String roleId = extractLdapAttr(roleDN,getRoleUidAttribute());
266 					if (roleId!=null) {
267 						NamingEnumeration rolesResults = searchRoleByWildcardedUid(roleId, cons);
268 						if (rolesResults.hasMore())
269 							if(rolesResults.nextElement()!=null)
270 								rolePrincipalUids.add(roleId);
271 					}
272 				}
273 			}
274 		}
275 		return (String[]) rolePrincipalUids.toArray(new String[rolePrincipalUids.size()]);
276 	}
277 
278 	/*
279 	 * (non-Javadoc)
280 	 * 
281 	 * @see org.apache.jetspeed.security.spi.impl.ldap.LdapMembershipDao#searchUsersFromGroupByUser(java.lang.String,
282 	 *      javax.naming.directory.SearchControls)
283 	 */
284 	public String[] searchRolesFromGroupByRole(final String groupPrincipalUid,
285 			SearchControls cons) throws NamingException {
286 
287 		String query = "(&(" + getRoleGroupMembershipForRoleAttribute() + "=" + getGroupDN(groupPrincipalUid) + ")" + getRoleFilter() + ")";
288 		
289 		if (logger.isDebugEnabled()) {
290 			logger.debug("query[" + query + "]");
291 		}
292 		
293 	    cons.setSearchScope(getSearchScope());
294 	    NamingEnumeration results = ((DirContext) ctx).search(getRoleFilterBase(),query , cons);	    
295 
296 		ArrayList rolePrincipalUids = new ArrayList();
297 
298 		while (results.hasMore()) {
299 			SearchResult result = (SearchResult) results.next();
300 			Attributes answer = result.getAttributes();
301 			rolePrincipalUids.addAll(getAttributes(getAttribute(getRoleIdAttribute(), answer)));
302 		}
303 		return (String[]) rolePrincipalUids
304 				.toArray(new String[rolePrincipalUids.size()]);
305 	}
306 
307 
308 	/* (non-Javadoc)
309 	 * @see org.apache.jetspeed.security.spi.impl.ldap.LdapMembershipDao#searchUsersFromRoleByRole(java.lang.String, javax.naming.directory.SearchControls)
310 	 */
311 	public String[] searchUsersFromRoleByRole(final String rolePrincipalUid, SearchControls cons)
312 	        throws NamingException
313 	{
314 	
315 		String query = "(&(" + getRoleIdAttribute() + "=" + (rolePrincipalUid) + ")" + getRoleFilter() + ")";
316 	    
317 		if (logger.isDebugEnabled())
318 	    {
319 	        logger.debug("query[" + query + "]");
320 	    }
321 	    
322 	    ArrayList userPrincipalUids=new ArrayList();
323 
324 	    cons.setSearchScope(getSearchScope());
325 	    NamingEnumeration results = ((DirContext) ctx).search(getRoleFilterBase(),query , cons);	    
326 		
327 	    while (results.hasMore())
328 	    {
329 	        SearchResult result = (SearchResult) results.next();
330 	        Attributes answer = result.getAttributes();
331 	        
332 	        Attribute userPrincipalUid = getAttribute(getRoleMembershipAttribute(), answer);
333 	        List attrs = getAttributes(userPrincipalUid);
334 	        Iterator it = attrs.iterator();
335 	        while(it.hasNext()) {
336 	        	String uidfull = (String)it.next();
337 	        	if (!StringUtils.isEmpty(uidfull)) {	        	
338 		        	String uid = extractLdapAttr(uidfull,getUserIdAttribute());
339 		        	if (uid!=null){
340 			        	userPrincipalUids.add(uid);
341 		        	}
342 	        	}
343 	        }
344 	    }
345 	    return (String[]) userPrincipalUids.toArray(new String[userPrincipalUids.size()]);
346 	}
347 
348 	/* (non-Javadoc)
349 	 * @see org.apache.jetspeed.security.spi.impl.ldap.LdapMembershipDao#searchUsersFromRoleByUser(java.lang.String, javax.naming.directory.SearchControls)
350 	 */
351 	public String[] searchUsersFromRoleByUser(final String rolePrincipalUid, SearchControls cons)
352 	throws NamingException
353 	{
354         String roleMemberAttr = getUserRoleMembershipAttribute();
355         /*
356          *  search for those users with a role membership attribute matching two possible values:  
357          *    - the role principal UID (e.g. 'admin') or
358          *    - the full DN of the role (e.g. 'cn=admin,ou=Roles,o=sevenSeas')     
359          */ 
360         StringBuffer byRolePrincipalUidMatch = new StringBuffer("(").append(roleMemberAttr).append("=").append(rolePrincipalUid).append(")");
361         StringBuffer byRoleDNMatch = new StringBuffer("(").append(roleMemberAttr).append("=").append(getRoleDN(rolePrincipalUid, true)).append(")");
362         
363         StringBuffer completeRoleAttrMatch = new StringBuffer("(|").append(byRolePrincipalUidMatch).append(byRoleDNMatch).append(")");
364         StringBuffer query= new StringBuffer("(&").append(completeRoleAttrMatch).append("(").append(getUserFilter()).append("))");
365         
366 		if (logger.isDebugEnabled())
367 		{
368 		    logger.debug("query[" + query + "]");
369 		}
370 	    
371 		cons.setSearchScope(getSearchScope());
372 	    NamingEnumeration results = ((DirContext) ctx).search(getUserFilterBase(),query.toString() , cons);	    
373 
374 		ArrayList userPrincipalUids = new ArrayList();
375 		
376 		while (results.hasMore())
377 		{
378 		    SearchResult result = (SearchResult) results.next();
379 		    Attributes answer = result.getAttributes();
380 		    userPrincipalUids.addAll(getAttributes(getAttribute(getUserIdAttribute(), answer)));
381 		}
382 		return (String[]) userPrincipalUids.toArray(new String[userPrincipalUids.size()]);
383 	}
384 
385     /***
386      * @param attr
387      * @return
388      * @throws NamingException
389      */
390     protected List getAttributes(Attribute attr) throws NamingException
391     {
392     	return getAttributes(attr, null);
393     }
394     /***
395      * @param attr
396      * @return
397      * @throws NamingException
398      */
399     protected List getAttributes(Attribute attr,String filter) throws NamingException
400     {
401         List uids = new ArrayList();
402         if (attr != null)
403         {
404             Enumeration groupUidEnum = attr.getAll();
405             while (groupUidEnum.hasMoreElements())
406             {
407             	String groupDN = (String)groupUidEnum.nextElement();
408             	if (filter==null) {
409             		uids.add(groupDN);
410             	} else if (filter!=null && groupDN.toLowerCase().indexOf(filter.toLowerCase())!=-1) {
411             		uids.add(groupDN);
412             	}
413             }
414         }
415         return uids;
416     }	
417 
418     /***
419      * @param results
420      * @return
421      * @throws NamingException
422      */
423     private Attributes getFirstUser(NamingEnumeration results) throws NamingException
424     {
425         SearchResult result = (SearchResult) results.next();
426         Attributes answer = result.getAttributes();
427 
428         return answer;
429     }
430     
431 
432 
433 	/***
434 	 * <p>
435 	 * A template method for defining the attributes for a particular LDAP class.
436 	 * </p>
437 	 * 
438 	 * @param principalUid The principal uid.
439 	 * @return the LDAP attributes object for the particular class.
440 	 */
441 	protected Attributes defineLdapAttributes(final String principalUid)
442 	{
443 	    Attributes attrs = new BasicAttributes(true);
444 	    BasicAttribute classes = new BasicAttribute("objectclass");
445 	
446 	    classes.add("top");
447 	    classes.add("person");
448 	    classes.add("organizationalPerson");
449 	    classes.add("inetorgperson");
450 	    attrs.put(classes);
451 	    attrs.put("cn", principalUid);
452 	    attrs.put("sn", principalUid);
453 	
454 	    return attrs;
455 	}
456 
457 	/***
458      * @see org.apache.jetspeed.security.spi.impl.ldap.LdapPrincipalDaoImpl#getDnSuffix()
459      */
460     protected String getDnSuffix()
461     {
462         return this.getUserFilterBase();
463     }
464 
465 	/***
466 	 * <p>
467 	 * Creates a GroupPrincipal object.
468 	 * </p>
469 	 * 
470 	 * @param principalUid The principal uid.
471 	 * @return A group principal object.
472 	 */
473 	protected Principal makePrincipal(String principalUid)
474 	{
475 	    return new UserPrincipalImpl(principalUid);
476 	}    
477 	
478 	private String extractLdapAttr(String dn,String ldapAttrName) {
479 
480 		String dnLowerCase = dn.toLowerCase();
481 		String ldapAttrNameLowerCase = ldapAttrName.toLowerCase();
482 		
483 		if (dnLowerCase.indexOf(ldapAttrNameLowerCase + "=")==-1)
484 			return null;
485 		
486 		if (dn.indexOf(",")!=-1 && dnLowerCase.indexOf(ldapAttrNameLowerCase + "=")!=-1)
487 			return dn.substring(dnLowerCase.indexOf(ldapAttrNameLowerCase)+ldapAttrName.length()+1,dn.indexOf(","));
488 		return dn.substring(dnLowerCase.indexOf(ldapAttrNameLowerCase)+ldapAttrName.length()+1,dn.length());
489 	}
490 
491 	protected String[] getObjectClasses() {
492 		return this.getUserObjectClasses();
493 	}
494 	
495 	protected String getUidAttributeForPrincipal() {
496 		return this.getUserUidAttribute();
497 	}
498 
499 	protected String[] getAttributes() {
500 		return getUserAttributes();
501 	}
502 
503 	protected String getEntryPrefix()
504     {
505         return this.getUidAttribute();
506 	}
507 
508 	protected String getSearchSuffix() {
509 		return this.getUserFilter();
510 	}	
511 }