1/*2 * Copyright 2000-2004 The Apache Software Foundation.3 * 4 * Licensed under the Apache License, Version 2.0 (the "License");5 * you may not use this file except in compliance with the License.6 * You may obtain a copy of the License at7 * 8 * http://www.apache.org/licenses/LICENSE-2.09 * 10 * Unless required by applicable law or agreed to in writing, software11 * distributed under the License is distributed on an "AS IS" BASIS,12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.13 * See the License for the specific language governing permissions and14 * limitations under the License.15 */1617packageorg.apache.jetspeed.services.security.ldap;
1819import java.util.Enumeration;
20import java.util.Iterator;
21import java.util.StringTokenizer;
22import java.util.Vector;
2324import javax.servlet.ServletConfig;
2526import org.apache.jetspeed.om.profile.Profile;
27import org.apache.jetspeed.om.profile.ProfileException;
28import org.apache.jetspeed.om.security.Role;
29import org.apache.jetspeed.om.security.UserNamePrincipal;
30import org.apache.jetspeed.om.security.ldap.LDAPRole;
31import org.apache.jetspeed.om.security.ldap.LDAPUser;
32import org.apache.jetspeed.services.JetspeedLDAP;
33import org.apache.jetspeed.services.JetspeedSecurity;
34import org.apache.jetspeed.services.Profiler;
35import org.apache.jetspeed.services.PsmlManager;
36import org.apache.jetspeed.services.ldap.LDAPURL;
37import org.apache.jetspeed.services.rundata.JetspeedRunData;
38import org.apache.jetspeed.services.rundata.JetspeedRunDataService;
39import org.apache.jetspeed.services.security.CachedAcl;
40import org.apache.jetspeed.services.security.JetspeedSecurityCache;
41import org.apache.jetspeed.services.security.JetspeedSecurityException;
42import org.apache.jetspeed.services.security.JetspeedSecurityService;
43import org.apache.jetspeed.services.security.RoleException;
44import org.apache.jetspeed.services.security.RoleManagement;
45import org.apache.jetspeed.services.security.UnknownUserException;
46import org.apache.turbine.services.InitializationException;
47import org.apache.turbine.services.TurbineBaseService;
48import org.apache.turbine.services.TurbineServices;
49import org.apache.turbine.services.resources.ResourceService;
50import org.apache.turbine.services.rundata.RunDataService;
5152/***53 *54 * @author <a href="mailto:ender@kilicoglu.nom.tr">Ender KILICOGLU</a>55 * @author <a href="mailto:sami.leino@netorek.fi">Sami Leino</a>56 *57 * @version $Id: LDAPRoleManagement.java,v 1.9 2004/02/23 03:52:33 jford Exp $58 *59 */60publicclassLDAPRoleManagementextends TurbineBaseService
61 implements RoleManagement62 {
63// Constants64privatefinalstatic String CASCADE_DELETE = "programmatic.cascade.delete";
65privatefinalstatic String CACHING_ENABLE = "caching.enable";
66privatefinalstaticboolean DEFAULT_CASCADE_DELETE = true;
67privatefinalstaticboolean DEFAULT_CACHING_ENABLE = true;
68privatefinalstatic String[] ATTRS = { "ou", "uid", "rolename", "rolepermissions" };
6970// Instance variables71privateJetspeedRunDataService runDataService = null;
72privateboolean cascadeDelete = false;
73privateboolean cachingEnable = false;
7475///////////////////////////////////////////////////////////////////////////76// Role Management Interfaces77///////////////////////////////////////////////////////////////////////////7879/***80 * Retrieves all <code>Role</code>s for a given username principal.81 *82 * The security service may optionally check the current user context83 * to determine if the requestor has permission to perform this action.84 *85 * @param username a user principal identity to be retrieved.86 * @return Iterator over all roles associated to the user principal.87 * @exception RoleException when the security provider has a general failure.88 * @exception InsufficientPrivilegeException when the requestor is denied due to insufficient privilege89 */90public Iterator getRoles(String username)
91 throws JetspeedSecurityException92 {
93 StringTokenizer st;
94LDAPUser user;
95try96 {
97if (cachingEnable)
98 {
99 Iterator result = JetspeedSecurityCache.getRoles(username);
100if (null != result)
101 {
102return result;
103 }
104 }
105 user = (LDAPUser)JetspeedSecurity.getUser(new UserNamePrincipal(username));
106 }
107catch(JetspeedSecurityException e)
108 {
109thrownewRoleException("Failed to Retrieve User: ", e);
110 }
111112 Vector roles= new Vector();
113114try115 {
116for (Enumeration enum = user.getGroupRoles().elements(); enum.hasMoreElements();)
117 {
118 st = new StringTokenizer((String)enum.nextElement(), ",");
119 st.nextToken();
120 roles.add(newLDAPRole(st.nextToken(), false));
121 }
122 }
123catch(Exception e)
124 {
125thrownewRoleException("Failed to retrieve groups ", e);
126 }
127return roles.iterator();
128129 }
130/***131 * Retrieves all <code>Role</code>s.132 *133 * The security service may optionally check the current user context134 * to determine if the requestor has permission to perform this action.135 *136 * @return Iterator over all roles.137 * @exception RoleException when the security provider has a general failure.138 * @exception InsufficientPrivilegeException when the requestor is denied due to insufficient privilege139 */140public Iterator getRoles()
141 throws JetspeedSecurityException142 {
143 Vector roles = new Vector();
144 Vector roleurls;
145146try147 {
148 roleurls = JetspeedLDAP.search(JetspeedLDAP.buildURL("ou=roles"),"(objectclass=jetspeedrole)", ATTRS, true);
149if (roleurls.size() > 0)
150 {
151for (Enumeration enum = roleurls.elements(); enum.hasMoreElements() ;)
152 {
153 roles.add(newLDAPRole((LDAPURL) (((Vector)enum.nextElement()).firstElement())));
154 }
155 }
156else157 {
158thrownewUnknownUserException("No role ");
159 }
160 }
161catch(Exception e)
162 {
163thrownewRoleException("Failed to retrieve roles ", e);
164 }
165return roles.iterator();
166167 }
168/***169 * Adds a <code>Role</code> into permanent storage.170 *171 * The security service may optionally check the current user context172 * to determine if the requestor has permission to perform this action.173 *174 * @exception RoleException when the security provider has a general failure.175 * @exception InsufficientPrivilegeException when the requestor is denied due to insufficient privilege176 */177publicvoid addRole(Role role)
178 throws JetspeedSecurityException179 {
180 LDAPRole ldapRole = null;
181182if(roleExists(role.getName()))
183 {
184thrownewRoleException("The role '" +
185 role.getName() + "' already exists");
186 }
187188try189 {
190 ldapRole = newLDAPRole(role.getName(), true);
191 ldapRole.update(true);
192 }
193catch(Exception e)
194 {
195thrownewRoleException("Failed to create role '" +
196 role.getName() + "'", e);
197 }
198199if (cachingEnable)
200 {
201 JetspeedSecurityCache.addRole(ldapRole);
202 }
203204try205 {
206 addDefaultRolePSML(ldapRole);
207 }
208catch (Exception e)
209 {
210try211 {
212 removeRole(ldapRole.getName());
213 }
214catch (Exception e2)
215 {
216 }
217thrownewRoleException("failed to add default PSML for Role resource", e);
218 }
219 }
220221protectedvoid addDefaultRolePSML(Role role)
222 throws RoleException223 {
224try225 {
226JetspeedRunDataService runDataService =
227 (JetspeedRunDataService)TurbineServices.getInstance()
228 .getService(RunDataService.SERVICE_NAME);
229JetspeedRunData rundata = runDataService.getCurrentRunData();
230Profile profile = Profiler.createProfile();
231 profile.setRole(role);
232 profile.setMediaType("html");
233 Profiler.createProfile(rundata, profile);
234 }
235catch (ProfileException e)
236 {
237try238 {
239 removeRole(role.getName());
240 }
241catch(Exception e2)
242 {
243 e.printStackTrace();
244 }
245thrownewRoleException("Failed to create Role PSML", e);
246 }
247 }
248249/***250 * Saves a <code>Role</code> into permanent storage.251 *252 * The security service can throw a <code>NotUniqueEntityException</code> when the public253 * credentials fail to meet the security provider-specific unique constraints.254 * The security service may optionally check the current user context255 * to determine if the requestor has permission to perform this action.256 *257 * @exception RoleException when the security provider has a general failure.258 * @exception InsufficientPrivilegeException when the requestor is denied due to insufficient privilege259 */260publicvoid saveRole(Role role)
261 throws JetspeedSecurityException262 {
263if(!roleExists(role.getName()))
264 {
265thrownewRoleException("The role '" +
266 role.getName() + "' doesn't exists");
267 }
268269try270 {
271272 }
273catch(Exception e)
274 {
275thrownewRoleException("Failed to create role '" +
276 role.getName() + "'", e);
277 }
278279 }
280/***281 * Removes a <code>Role</code> from the permanent store.282 *283 * The security service may optionally check the current user context284 * to determine if the requestor has permission to perform this action.285 *286 * @param roleName the principal identity of the role to be retrieved.287 * @exception RoleException when the security provider has a general failure.288 * @exception InsufficientPrivilegeException when the requestor is denied due to insufficient privilege289 */290publicvoid removeRole(String roleName)
291 throws JetspeedSecurityException292 {
293try294 {
295LDAPRole role = newLDAPRole(roleName, false);
296 JetspeedLDAP.deleteEntry(role.getldapurl());
297 PsmlManager.removeRoleDocuments(role);
298299if(cascadeDelete)
300 {
301 }
302303if (cachingEnable)
304 {
305 JetspeedSecurityCache.removeAllRoles(roleName);
306 }
307 }
308catch(Exception e)
309 {
310thrownewRoleException("Failed to remove group '" +
311 roleName + "'", e);
312 }
313 }
314315/***316 * Grants a role to a user.317 *318 * The security service may optionally check the current user context319 * to determine if the requestor has permission to perform this action.320 *321 * @exception RoleException when the security provider has a general failure retrieving users.322 * @exception InsufficientPrivilegeException when the requestor is denied due to insufficient privilege323 */324publicvoid grantRole(String username, String roleName)
325 throws JetspeedSecurityException326 {
327 grantRole(username, roleName, JetspeedSecurity.JETSPEED_GROUP);
328 }
329330publicvoid grantRole(String username, String roleName, String groupName)
331 throws JetspeedSecurityException332 {
333LDAPUser user;
334LDAPRole role;
335try336 {
337 user = (LDAPUser)JetspeedSecurity.getUser(new UserNamePrincipal(username));
338 role = (LDAPRole)JetspeedSecurity.getRole(roleName);
339 }
340catch(JetspeedSecurityException e)
341342 {
343thrownewRoleException("Failed to Retrieve User or Role: ", e);
344 }
345346try347 {
348 user.addGroupRole(groupName, roleName);
349 user.update(false);
350351if (cachingEnable)
352 {
353 JetspeedSecurityCache.addRole(username, role);
354 }
355 }
356catch(Exception e)
357 {
358thrownewRoleException("Failed to add role info ", e);
359 }
360 }
361362/***363 * Revokes a role from a user.364 *365 * The security service may optionally check the current user context366 * to determine if the requestor has permission to perform this action.367 *368 * @exception RoleException when the security provider has a general failure retrieving users.369 * @exception InsufficientPrivilegeException when the requestor is denied due to insufficient privilege370 */371publicvoid revokeRole(String username, String rolename)
372 throws JetspeedSecurityException373 {
374 revokeRole(username, rolename, JetspeedSecurity.JETSPEED_GROUP);
375 }
376377publicvoid revokeRole(String username, String rolename, String groupname)
378 throws JetspeedSecurityException379 {
380LDAPUser user;
381382try383 {
384 user = (LDAPUser)JetspeedSecurity.getUser(new UserNamePrincipal(username));
385 }
386catch(JetspeedSecurityException e)
387 {
388thrownewRoleException("Failed to Retrieve User: ", e);
389 }
390391try392 {
393 user.removeGroupRole(groupname, rolename);
394 user.update(false);
395396if (cachingEnable)
397 {
398 JetspeedSecurityCache.removeRole(username, rolename, groupname);
399 }
400 }
401catch(Exception e)
402 {
403thrownewRoleException("Failed to add role info ", e);
404 }
405 }
406407/***408 * Checks for the relationship of user has a role. Returns true when the user has the given role.409 *410 * The security service may optionally check the current user context411 * to determine if the requestor has permission to perform this action.412 *413 * @exception RoleException when the security provider has a general failure retrieving users.414 * @exception InsufficientPrivilegeException when the requestor is denied due to insufficient privilege415 */416publicboolean hasRole(String username, String roleName)
417 throws JetspeedSecurityException418 {
419return hasRole(username, roleName, JetspeedSecurity.JETSPEED_GROUP);
420 }
421422publicboolean hasRole(String username, String roleName, String groupName)
423 throws JetspeedSecurityException424 {
425 StringTokenizer st;
426LDAPUser user;
427try428 {
429if (cachingEnable)
430 {
431CachedAcl acl = JetspeedSecurityCache.getAcl(username);
432if (null != acl)
433 {
434return acl.hasRole(roleName, groupName);
435 }
436 }
437 user = (LDAPUser)JetspeedSecurity.getUser(new UserNamePrincipal(username));
438 }
439catch(JetspeedSecurityException e)
440 {
441thrownewRoleException("Failed to Retrieve User: ", e);
442 }
443try444 {
445for (Enumeration enum = user.getGroupRoles().elements(); enum.hasMoreElements();)
446 {
447 st = new StringTokenizer((String)enum.nextElement(),",");
448 String gn = st.nextToken();
449 String rn = st.nextToken();
450if (rn.equalsIgnoreCase(roleName) && gn.equalsIgnoreCase(groupName))
451 {
452returntrue;
453 }
454 }
455 }
456catch(Exception e)
457 {
458thrownewRoleException("Failed to retrieve roles ", e);
459 }
460return false;
461 }
462463/***464 * Retrieves a single <code>Role</code> for a given roleName principal.465 *466 * The security service may optionally check the current user context467 * to determine if the requestor has permission to perform this action.468 *469 * @param roleName a role principal identity to be retrieved.470 * @return Role the role record retrieved.471 * @exception RoleException when the security provider has a general failure.472 * @exception InsufficientPrivilegeException when the requestor is denied due to insufficient privilege473 */474publicRole getRole(String roleName)
475 throws JetspeedSecurityException476 {
477 Vector roleurls;
478479try480 {
481 roleurls = JetspeedLDAP.search(JetspeedLDAP.buildURL("ou=roles"),
482"(&(uid=" + roleName + ")(objectclass=jetspeedrole))", ATTRS, true);
483484if (roleurls.size() == 1)
485 {
486returnnewLDAPRole((LDAPURL) ((Vector)roleurls.elementAt(0)).firstElement());
487 }
488elseif(roleurls.size() > 1)
489 {
490thrownewRoleException("Multiple roles with same name");
491 }
492 }
493catch(Exception e)
494 {
495thrownewRoleException("Failed to retrieve roles ", e);
496 }
497thrownewRoleException("Unknown role '" + roleName + "'");
498 }
499500///////////////////////////////////////////////////////////////////////////501// Internal502///////////////////////////////////////////////////////////////////////////503504protectedJetspeedRunData getRunData()
505 {
506JetspeedRunData rundata = null;
507if (this.runDataService != null)
508 {
509 rundata = this.runDataService.getCurrentRunData();
510 }
511return rundata;
512 }
513514/***515 * Check whether a specified role exists.516 *517 * The login name is used for looking up the account.518 *519 * @param roleName the name of the role to check for existence.520 * @return true if the specified account exists521 * @throws RoleException if there was a general db access error522 *523 */524protectedboolean roleExists(String roleName)
525 throws RoleException526 {
527 Vector roleurls;
528529try530 {
531 roleurls = JetspeedLDAP.search(JetspeedLDAP.buildURL("ou=roles"),
532"(&(uid=" + roleName + ")(objectclass=jetspeedrole))", ATTRS, true);
533if (roleurls.size() > 0)
534 {
535returntrue;
536 }
537 }
538catch(Exception e)
539 {
540thrownewRoleException("Failed to retrieve roles ", e);
541 }
542return false;
543 }
544545///////////////////////////////////////////////////////////////////////////546// Service Init547///////////////////////////////////////////////////////////////////////////548549/***550 * This is the early initialization method called by the551 * Turbine <code>Service</code> framework552 * @param conf The <code>ServletConfig</code>553 * @exception throws a <code>InitializationException</code> if the service554 * fails to initialize555 */556publicsynchronizedvoid init(ServletConfig conf)
557 throws InitializationException
558 {
559if (getInit()) return;
560561super.init(conf);
562563// get configuration parameters from Jetspeed Resources564 ResourceService serviceConf = ((TurbineServices)TurbineServices.getInstance())
565 .getResources(JetspeedSecurityService.SERVICE_NAME);
566567this.runDataService =
568 (JetspeedRunDataService)TurbineServices.getInstance()
569 .getService(RunDataService.SERVICE_NAME);
570571 cascadeDelete = serviceConf.getBoolean( CASCADE_DELETE, DEFAULT_CASCADE_DELETE );
572 cachingEnable = serviceConf.getBoolean( CACHING_ENABLE, DEFAULT_CACHING_ENABLE );
573 setInit(true);
574 }
575576 }