1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.jetspeed.services.security.ldap;
18
19 import java.util.Enumeration;
20 import java.util.Iterator;
21 import java.util.StringTokenizer;
22 import java.util.Vector;
23
24 import javax.servlet.ServletConfig;
25
26 import org.apache.jetspeed.om.profile.Profile;
27 import org.apache.jetspeed.om.profile.ProfileException;
28 import org.apache.jetspeed.om.security.Role;
29 import org.apache.jetspeed.om.security.UserNamePrincipal;
30 import org.apache.jetspeed.om.security.ldap.LDAPRole;
31 import org.apache.jetspeed.om.security.ldap.LDAPUser;
32 import org.apache.jetspeed.services.JetspeedLDAP;
33 import org.apache.jetspeed.services.JetspeedSecurity;
34 import org.apache.jetspeed.services.Profiler;
35 import org.apache.jetspeed.services.PsmlManager;
36 import org.apache.jetspeed.services.ldap.LDAPURL;
37 import org.apache.jetspeed.services.rundata.JetspeedRunData;
38 import org.apache.jetspeed.services.rundata.JetspeedRunDataService;
39 import org.apache.jetspeed.services.security.CachedAcl;
40 import org.apache.jetspeed.services.security.JetspeedSecurityCache;
41 import org.apache.jetspeed.services.security.JetspeedSecurityException;
42 import org.apache.jetspeed.services.security.JetspeedSecurityService;
43 import org.apache.jetspeed.services.security.RoleException;
44 import org.apache.jetspeed.services.security.RoleManagement;
45 import org.apache.jetspeed.services.security.UnknownUserException;
46 import org.apache.turbine.services.InitializationException;
47 import org.apache.turbine.services.TurbineBaseService;
48 import org.apache.turbine.services.TurbineServices;
49 import org.apache.turbine.services.resources.ResourceService;
50 import org.apache.turbine.services.rundata.RunDataService;
51
52 /***
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 */
60 public class LDAPRoleManagement extends TurbineBaseService
61 implements RoleManagement
62 {
63
64 private final static String CASCADE_DELETE = "programmatic.cascade.delete";
65 private final static String CACHING_ENABLE = "caching.enable";
66 private final static boolean DEFAULT_CASCADE_DELETE = true;
67 private final static boolean DEFAULT_CACHING_ENABLE = true;
68 private final static String[] ATTRS = { "ou", "uid", "rolename", "rolepermissions" };
69
70
71 private JetspeedRunDataService runDataService = null;
72 private boolean cascadeDelete = false;
73 private boolean cachingEnable = false;
74
75
76
77
78
79 /***
80 * Retrieves all <code>Role</code>s for a given username principal.
81 *
82 * The security service may optionally check the current user context
83 * 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 privilege
89 */
90 public Iterator getRoles(String username)
91 throws JetspeedSecurityException
92 {
93 StringTokenizer st;
94 LDAPUser user;
95 try
96 {
97 if (cachingEnable)
98 {
99 Iterator result = JetspeedSecurityCache.getRoles(username);
100 if (null != result)
101 {
102 return result;
103 }
104 }
105 user = (LDAPUser)JetspeedSecurity.getUser(new UserNamePrincipal(username));
106 }
107 catch(JetspeedSecurityException e)
108 {
109 throw new RoleException("Failed to Retrieve User: ", e);
110 }
111
112 Vector roles= new Vector();
113
114 try
115 {
116 for (Enumeration enum = user.getGroupRoles().elements(); enum.hasMoreElements();)
117 {
118 st = new StringTokenizer((String)enum.nextElement(), ",");
119 st.nextToken();
120 roles.add(new LDAPRole(st.nextToken(), false));
121 }
122 }
123 catch(Exception e)
124 {
125 throw new RoleException("Failed to retrieve groups ", e);
126 }
127 return roles.iterator();
128
129 }
130 /***
131 * Retrieves all <code>Role</code>s.
132 *
133 * The security service may optionally check the current user context
134 * 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 privilege
139 */
140 public Iterator getRoles()
141 throws JetspeedSecurityException
142 {
143 Vector roles = new Vector();
144 Vector roleurls;
145
146 try
147 {
148 roleurls = JetspeedLDAP.search(JetspeedLDAP.buildURL("ou=roles"),"(objectclass=jetspeedrole)", ATTRS, true);
149 if (roleurls.size() > 0)
150 {
151 for (Enumeration enum = roleurls.elements(); enum.hasMoreElements() ;)
152 {
153 roles.add(new LDAPRole((LDAPURL) (((Vector)enum.nextElement()).firstElement())));
154 }
155 }
156 else
157 {
158 throw new UnknownUserException("No role ");
159 }
160 }
161 catch(Exception e)
162 {
163 throw new RoleException("Failed to retrieve roles ", e);
164 }
165 return roles.iterator();
166
167 }
168 /***
169 * Adds a <code>Role</code> into permanent storage.
170 *
171 * The security service may optionally check the current user context
172 * 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 privilege
176 */
177 public void addRole(Role role)
178 throws JetspeedSecurityException
179 {
180 LDAPRole ldapRole = null;
181
182 if(roleExists(role.getName()))
183 {
184 throw new RoleException("The role '" +
185 role.getName() + "' already exists");
186 }
187
188 try
189 {
190 ldapRole = new LDAPRole(role.getName(), true);
191 ldapRole.update(true);
192 }
193 catch(Exception e)
194 {
195 throw new RoleException("Failed to create role '" +
196 role.getName() + "'", e);
197 }
198
199 if (cachingEnable)
200 {
201 JetspeedSecurityCache.addRole(ldapRole);
202 }
203
204 try
205 {
206 addDefaultRolePSML(ldapRole);
207 }
208 catch (Exception e)
209 {
210 try
211 {
212 removeRole(ldapRole.getName());
213 }
214 catch (Exception e2)
215 {
216 }
217 throw new RoleException("failed to add default PSML for Role resource", e);
218 }
219 }
220
221 protected void addDefaultRolePSML(Role role)
222 throws RoleException
223 {
224 try
225 {
226 JetspeedRunDataService runDataService =
227 (JetspeedRunDataService)TurbineServices.getInstance()
228 .getService(RunDataService.SERVICE_NAME);
229 JetspeedRunData rundata = runDataService.getCurrentRunData();
230 Profile profile = Profiler.createProfile();
231 profile.setRole(role);
232 profile.setMediaType("html");
233 Profiler.createProfile(rundata, profile);
234 }
235 catch (ProfileException e)
236 {
237 try
238 {
239 removeRole(role.getName());
240 }
241 catch(Exception e2)
242 {
243 e.printStackTrace();
244 }
245 throw new RoleException("Failed to create Role PSML", e);
246 }
247 }
248
249 /***
250 * Saves a <code>Role</code> into permanent storage.
251 *
252 * The security service can throw a <code>NotUniqueEntityException</code> when the public
253 * credentials fail to meet the security provider-specific unique constraints.
254 * The security service may optionally check the current user context
255 * 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 privilege
259 */
260 public void saveRole(Role role)
261 throws JetspeedSecurityException
262 {
263 if(!roleExists(role.getName()))
264 {
265 throw new RoleException("The role '" +
266 role.getName() + "' doesn't exists");
267 }
268
269 try
270 {
271
272 }
273 catch(Exception e)
274 {
275 throw new RoleException("Failed to create role '" +
276 role.getName() + "'", e);
277 }
278
279 }
280 /***
281 * Removes a <code>Role</code> from the permanent store.
282 *
283 * The security service may optionally check the current user context
284 * 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 privilege
289 */
290 public void removeRole(String roleName)
291 throws JetspeedSecurityException
292 {
293 try
294 {
295 LDAPRole role = new LDAPRole(roleName, false);
296 JetspeedLDAP.deleteEntry(role.getldapurl());
297 PsmlManager.removeRoleDocuments(role);
298
299 if(cascadeDelete)
300 {
301 }
302
303 if (cachingEnable)
304 {
305 JetspeedSecurityCache.removeAllRoles(roleName);
306 }
307 }
308 catch(Exception e)
309 {
310 throw new RoleException("Failed to remove group '" +
311 roleName + "'", e);
312 }
313 }
314
315 /***
316 * Grants a role to a user.
317 *
318 * The security service may optionally check the current user context
319 * 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 privilege
323 */
324 public void grantRole(String username, String roleName)
325 throws JetspeedSecurityException
326 {
327 grantRole(username, roleName, JetspeedSecurity.JETSPEED_GROUP);
328 }
329
330 public void grantRole(String username, String roleName, String groupName)
331 throws JetspeedSecurityException
332 {
333 LDAPUser user;
334 LDAPRole role;
335 try
336 {
337 user = (LDAPUser)JetspeedSecurity.getUser(new UserNamePrincipal(username));
338 role = (LDAPRole)JetspeedSecurity.getRole(roleName);
339 }
340 catch(JetspeedSecurityException e)
341
342 {
343 throw new RoleException("Failed to Retrieve User or Role: ", e);
344 }
345
346 try
347 {
348 user.addGroupRole(groupName, roleName);
349 user.update(false);
350
351 if (cachingEnable)
352 {
353 JetspeedSecurityCache.addRole(username, role);
354 }
355 }
356 catch(Exception e)
357 {
358 throw new RoleException("Failed to add role info ", e);
359 }
360 }
361
362 /***
363 * Revokes a role from a user.
364 *
365 * The security service may optionally check the current user context
366 * 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 privilege
370 */
371 public void revokeRole(String username, String rolename)
372 throws JetspeedSecurityException
373 {
374 revokeRole(username, rolename, JetspeedSecurity.JETSPEED_GROUP);
375 }
376
377 public void revokeRole(String username, String rolename, String groupname)
378 throws JetspeedSecurityException
379 {
380 LDAPUser user;
381
382 try
383 {
384 user = (LDAPUser)JetspeedSecurity.getUser(new UserNamePrincipal(username));
385 }
386 catch(JetspeedSecurityException e)
387 {
388 throw new RoleException("Failed to Retrieve User: ", e);
389 }
390
391 try
392 {
393 user.removeGroupRole(groupname, rolename);
394 user.update(false);
395
396 if (cachingEnable)
397 {
398 JetspeedSecurityCache.removeRole(username, rolename, groupname);
399 }
400 }
401 catch(Exception e)
402 {
403 throw new RoleException("Failed to add role info ", e);
404 }
405 }
406
407 /***
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 context
411 * 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 privilege
415 */
416 public boolean hasRole(String username, String roleName)
417 throws JetspeedSecurityException
418 {
419 return hasRole(username, roleName, JetspeedSecurity.JETSPEED_GROUP);
420 }
421
422 public boolean hasRole(String username, String roleName, String groupName)
423 throws JetspeedSecurityException
424 {
425 StringTokenizer st;
426 LDAPUser user;
427 try
428 {
429 if (cachingEnable)
430 {
431 CachedAcl acl = JetspeedSecurityCache.getAcl(username);
432 if (null != acl)
433 {
434 return acl.hasRole(roleName, groupName);
435 }
436 }
437 user = (LDAPUser)JetspeedSecurity.getUser(new UserNamePrincipal(username));
438 }
439 catch(JetspeedSecurityException e)
440 {
441 throw new RoleException("Failed to Retrieve User: ", e);
442 }
443 try
444 {
445 for (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();
450 if (rn.equalsIgnoreCase(roleName) && gn.equalsIgnoreCase(groupName))
451 {
452 return true;
453 }
454 }
455 }
456 catch(Exception e)
457 {
458 throw new RoleException("Failed to retrieve roles ", e);
459 }
460 return false;
461 }
462
463 /***
464 * Retrieves a single <code>Role</code> for a given roleName principal.
465 *
466 * The security service may optionally check the current user context
467 * 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 privilege
473 */
474 public Role getRole(String roleName)
475 throws JetspeedSecurityException
476 {
477 Vector roleurls;
478
479 try
480 {
481 roleurls = JetspeedLDAP.search(JetspeedLDAP.buildURL("ou=roles"),
482 "(&(uid=" + roleName + ")(objectclass=jetspeedrole))", ATTRS, true);
483
484 if (roleurls.size() == 1)
485 {
486 return new LDAPRole((LDAPURL) ((Vector)roleurls.elementAt(0)).firstElement());
487 }
488 else if(roleurls.size() > 1)
489 {
490 throw new RoleException("Multiple roles with same name");
491 }
492 }
493 catch(Exception e)
494 {
495 throw new RoleException("Failed to retrieve roles ", e);
496 }
497 throw new RoleException("Unknown role '" + roleName + "'");
498 }
499
500
501
502
503
504 protected JetspeedRunData getRunData()
505 {
506 JetspeedRunData rundata = null;
507 if (this.runDataService != null)
508 {
509 rundata = this.runDataService.getCurrentRunData();
510 }
511 return rundata;
512 }
513
514 /***
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 exists
521 * @throws RoleException if there was a general db access error
522 *
523 */
524 protected boolean roleExists(String roleName)
525 throws RoleException
526 {
527 Vector roleurls;
528
529 try
530 {
531 roleurls = JetspeedLDAP.search(JetspeedLDAP.buildURL("ou=roles"),
532 "(&(uid=" + roleName + ")(objectclass=jetspeedrole))", ATTRS, true);
533 if (roleurls.size() > 0)
534 {
535 return true;
536 }
537 }
538 catch(Exception e)
539 {
540 throw new RoleException("Failed to retrieve roles ", e);
541 }
542 return false;
543 }
544
545
546
547
548
549 /***
550 * This is the early initialization method called by the
551 * Turbine <code>Service</code> framework
552 * @param conf The <code>ServletConfig</code>
553 * @exception throws a <code>InitializationException</code> if the service
554 * fails to initialize
555 */
556 public synchronized void init(ServletConfig conf)
557 throws InitializationException
558 {
559 if (getInit()) return;
560
561 super.init(conf);
562
563
564 ResourceService serviceConf = ((TurbineServices)TurbineServices.getInstance())
565 .getResources(JetspeedSecurityService.SERVICE_NAME);
566
567 this.runDataService =
568 (JetspeedRunDataService)TurbineServices.getInstance()
569 .getService(RunDataService.SERVICE_NAME);
570
571 cascadeDelete = serviceConf.getBoolean( CASCADE_DELETE, DEFAULT_CASCADE_DELETE );
572 cachingEnable = serviceConf.getBoolean( CACHING_ENABLE, DEFAULT_CACHING_ENABLE );
573 setInit(true);
574 }
575
576 }