View Javadoc

1   package org.apache.turbine.services.security.ldap;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.Hashtable;
23  import java.util.Iterator;
24  import java.util.Vector;
25  import javax.naming.NameAlreadyBoundException;
26  import javax.naming.NamingEnumeration;
27  import javax.naming.NamingException;
28  import javax.naming.directory.Attribute;
29  import javax.naming.directory.Attributes;
30  import javax.naming.directory.BasicAttribute;
31  import javax.naming.directory.BasicAttributes;
32  import javax.naming.directory.DirContext;
33  import javax.naming.directory.SearchControls;
34  import javax.naming.directory.SearchResult;
35  
36  import org.apache.commons.logging.Log;
37  import org.apache.commons.logging.LogFactory;
38  import org.apache.torque.util.Criteria;
39  import org.apache.turbine.om.security.Group;
40  import org.apache.turbine.om.security.Permission;
41  import org.apache.turbine.om.security.Role;
42  import org.apache.turbine.om.security.TurbineGroup;
43  import org.apache.turbine.om.security.TurbinePermission;
44  import org.apache.turbine.om.security.TurbineRole;
45  import org.apache.turbine.om.security.User;
46  import org.apache.turbine.services.security.BaseSecurityService;
47  import org.apache.turbine.services.security.TurbineSecurity;
48  import org.apache.turbine.util.security.AccessControlList;
49  import org.apache.turbine.util.security.DataBackendException;
50  import org.apache.turbine.util.security.EntityExistsException;
51  import org.apache.turbine.util.security.GroupSet;
52  import org.apache.turbine.util.security.PermissionSet;
53  import org.apache.turbine.util.security.RoleSet;
54  import org.apache.turbine.util.security.UnknownEntityException;
55  
56  /***
57   * An implementation of SecurityService that uses LDAP as a backend.
58   *
59   * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
60   * @author <a href="mailto:tadewunmi@gluecode.com">Tracy M. Adewunmi </a>
61   * @author <a href="mailto:lflournoy@gluecode.com">Leonard J. Flournoy </a>
62   * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
63   * @author <a href="mailto:marco@intermeta.de">Marco Kn&uuml;ttel</a>
64   * @author <a href="mailto:hhernandez@itweb.com.mx">Humberto Hernandez</a>
65   * @version $Id: LDAPSecurityService.java 534527 2007-05-02 16:10:59Z tv $
66   */
67  public class LDAPSecurityService extends BaseSecurityService
68  {
69  
70      /*** Logging */
71      private static Log log = LogFactory.getLog(LDAPSecurityService.class);
72  
73      /*
74       * -----------------------------------------------------------------------
75       *  C R E A T I O N  O F  A C C E S S  C O N T R O L  L I S T
76       * -----------------------------------------------------------------------
77       */
78  
79      /***
80       * Constructs an AccessControlList for a specific user.
81       *
82       * This method creates a snapshot of the state of security information
83       * concerning this user, at the moment of invocation and stores it
84       * into an AccessControlList object.
85       *
86       * @param user the user for whom the AccessControlList are to be retrieved
87       * @throws DataBackendException if there was an error accessing the backend.
88       * @throws UnknownEntityException if user account is not present.
89       * @return an AccessControlList for a specific user.
90       */
91      public AccessControlList getACL(User user)
92              throws DataBackendException, UnknownEntityException
93      {
94          if (!TurbineSecurity.accountExists(user))
95          {
96              throw new UnknownEntityException("The account '"
97                      + user.getName() + "' does not exist");
98          }
99          try
100         {
101             Hashtable roles = new Hashtable();
102             Hashtable permissions = new Hashtable();
103 
104             // notify the state modifiers (writers) that we want to create
105             // the snapshot.
106             lockShared();
107 
108             // construct the snapshot:
109             // foreach group in the system
110             Iterator groupsIterator = getAllGroups().iterator();
111 
112             while (groupsIterator.hasNext())
113             {
114                 Group group = (Group) groupsIterator.next();
115 
116                 // get roles of user in the group
117                 RoleSet groupRoles = getRoles(user, group);
118 
119                 // put the Set into roles(group)
120                 roles.put(group, groupRoles);
121                 // collect all permissoins in this group
122                 PermissionSet groupPermissions = new PermissionSet();
123                 // foreach role in Set
124                 Iterator rolesIterator = groupRoles.iterator();
125 
126                 while (rolesIterator.hasNext())
127                 {
128                     Role role = (Role) rolesIterator.next();
129                     // get permissions of the role
130                     PermissionSet rolePermissions = getPermissions(role);
131 
132                     groupPermissions.add(rolePermissions);
133                 }
134                 // put the Set into permissions(group)
135                 permissions.put(group, groupPermissions);
136             }
137             return getAclInstance(roles, permissions);
138         }
139         catch (Exception e)
140         {
141             throw new DataBackendException("Failed to build ACL for user '"
142                     + user.getName() + "'", e);
143         }
144         finally
145         {
146             // notify the state modifiers that we are done creating
147             // the snapshot.
148             unlockShared();
149         }
150     }
151 
152     /*
153      * -----------------------------------------------------------------------
154      * S E C U R I T Y  M A N A G E M E N T
155      * -----------------------------------------------------------------------
156      */
157 
158     /***
159      * Grant an User a Role in a Group.
160      *
161      * @param user the user.
162      * @param group the group.
163      * @param role the role.
164      * @throws DataBackendException if there was an error accessing the backend.
165      * @throws UnknownEntityException if user account, group or role
166      *         is not present.
167      */
168     public synchronized void grant(User user, Group group, Role role)
169             throws DataBackendException, UnknownEntityException
170     {
171         try
172         {
173             lockExclusive();
174 
175             String userName = user.getName();
176             String roleName = role.getName();
177             String groupName = group.getName();
178 
179             if (!accountExists(user))
180             {
181                 throw new UnknownEntityException(
182                         "User '" + userName + "' does not exist");
183             }
184 
185             if (!checkExists(role))
186             {
187                 throw new UnknownEntityException(
188                         "Role '" + roleName + "' does not exist");
189             }
190 
191             if (!checkExists(group))
192             {
193                 throw new UnknownEntityException(
194                         "Group '" + groupName + "' does not exist");
195             }
196 
197             // Make the distinguished name.
198             String dn = "turbineGroupName=" + groupName + ","
199                     + LDAPSecurityConstants.getNameAttribute()
200                     + "=" + userName + ","
201                     + LDAPSecurityConstants.getBaseSearch();
202 
203 
204             // Connect to LDAP.
205             DirContext ctx = LDAPUserManager.bindAsAdmin();
206 
207             // Make the attributes.
208             Attributes attrs = new BasicAttributes();
209 
210             attrs.put(new BasicAttribute("turbineRoleName", roleName));
211             attrs.put(new BasicAttribute("objectClass", "turbineUserGroup"));
212             attrs.put(new BasicAttribute("turbineUserUniqueId", userName));
213             try
214             {
215                 // Add the turbineUserGroup.
216                 ctx.bind(dn, null, attrs);
217             }
218             catch (NameAlreadyBoundException ex)
219             {
220                 // Since turbineUserGroup had already been created
221                 // then just add the role name attribute.
222                 attrs = new BasicAttributes();
223                 attrs.put(new BasicAttribute("turbineRoleName", roleName));
224                 ctx.modifyAttributes(dn, DirContext.ADD_ATTRIBUTE, attrs);
225             }
226 
227         }
228         catch (NamingException ex)
229         {
230             throw new DataBackendException("NamingException caught", ex);
231         }
232         finally
233         {
234             unlockExclusive();
235         }
236     }
237 
238     /***
239      * Revoke a Role in a Group from an User.
240      *
241      * @param user the user.
242      * @param group the group.
243      * @param role the role.
244      * @throws DataBackendException if there was an error accessing the backend.
245      * @throws UnknownEntityException if user account, group or role is
246      *         not present.
247      */
248     public synchronized void revoke(User user, Group group, Role role)
249             throws DataBackendException, UnknownEntityException
250     {
251         try
252         {
253             lockExclusive();
254 
255             String userName = user.getName();
256             String roleName = role.getName();
257             String groupName = group.getName();
258 
259             if (!accountExists(user))
260             {
261                 throw new UnknownEntityException(
262                         "User '" + userName + "' does not exist");
263             }
264 
265             if (!checkExists(role))
266             {
267                 throw new UnknownEntityException(
268                         "Role '" + roleName + "' does not exist");
269             }
270 
271             if (!checkExists(group))
272             {
273                 throw new UnknownEntityException(
274                         "Group '" + groupName + "' does not exist");
275             }
276 
277             // Make the distinguished name.
278             String dn = "turbineGroupName=" + groupName + ","
279                     + LDAPSecurityConstants.getNameAttribute()
280                     + "=" + userName + ","
281                     + LDAPSecurityConstants.getBaseSearch();
282 
283             // Make the attributes.
284             Attributes attrs = new BasicAttributes();
285 
286             attrs.put(new BasicAttribute("turbineRoleName", roleName));
287 
288             // Connect to LDAP.
289             DirContext ctx = LDAPUserManager.bindAsAdmin();
290 
291             // Remove the role.
292             ctx.modifyAttributes(dn, DirContext.REMOVE_ATTRIBUTE, attrs);
293 
294         }
295         catch (NamingException ex)
296         {
297             throw new DataBackendException("NamingException caught", ex);
298         }
299         finally
300         {
301             unlockExclusive();
302         }
303     }
304 
305     /***
306      * Grants a Role a Permission
307      *
308      * @param role the Role.
309      * @param permission the Permission.
310      * @throws DataBackendException if there was an error accessing the backend.
311      * @throws UnknownEntityException if role or permission is not present.
312      */
313     public synchronized void grant(Role role, Permission permission)
314             throws DataBackendException, UnknownEntityException
315     {
316         try
317         {
318             lockExclusive();
319 
320             String roleName = role.getName();
321             String permName = permission.getName();
322 
323             if (!checkExists(role))
324             {
325                 throw new UnknownEntityException(
326                         "Role '" + roleName + "' does not exist");
327             }
328 
329             if (!checkExists(permission))
330             {
331                 throw new UnknownEntityException(
332                         "Permission '" + permName + "' does not exist");
333             }
334 
335             // Make the distinguished name.
336             String dn = "turbineRoleName=" + roleName + ","
337                     + LDAPSecurityConstants.getBaseSearch();
338 
339             // Make the attributes.
340             Attributes attrs = new BasicAttributes();
341 
342             attrs.put(new BasicAttribute("turbinePermissionName", permName));
343 
344             // Connect to LDAP.
345             DirContext ctx = LDAPUserManager.bindAsAdmin();
346 
347             // Add the permission.
348             ctx.modifyAttributes(dn, DirContext.ADD_ATTRIBUTE, attrs);
349 
350         }
351         catch (NamingException ex)
352         {
353             throw new DataBackendException("NamingException caught", ex);
354         }
355         finally
356         {
357             unlockExclusive();
358         }
359     }
360 
361     /***
362      * Revokes a Permission from a Role.
363      *
364      * @param role the Role.
365      * @param permission the Permission.
366      * @throws DataBackendException if there was an error accessing the backend.
367      * @throws UnknownEntityException if role or permission is not present.
368      */
369     public synchronized void revoke(Role role, Permission permission)
370             throws DataBackendException, UnknownEntityException
371     {
372         try
373         {
374             lockExclusive();
375 
376             String roleName = role.getName();
377             String permName = permission.getName();
378 
379             if (!checkExists(role))
380             {
381                 throw new UnknownEntityException(
382                         "Role '" + roleName + "' does not exist");
383             }
384 
385             if (!checkExists(permission))
386             {
387                 throw new UnknownEntityException(
388                         "Permission '" + permName + "' does not exist");
389             }
390 
391             // Make the distinguished name.
392             String dn = "turbineRoleName=" + roleName + ","
393                     + LDAPSecurityConstants.getBaseSearch();
394 
395             // Make the attributes.
396             Attributes attrs = new BasicAttributes();
397 
398             attrs.put(new BasicAttribute("turbinePermissionName", permName));
399 
400             // Connect to LDAP.
401             DirContext ctx = LDAPUserManager.bindAsAdmin();
402 
403             // Remove the permission.
404             ctx.modifyAttributes(dn, DirContext.REMOVE_ATTRIBUTE, attrs);
405 
406         }
407         catch (NamingException ex)
408         {
409             throw new DataBackendException("NamingException caught", ex);
410         }
411         finally
412         {
413             unlockExclusive();
414         }
415     }
416 
417     /*
418      * -----------------------------------------------------------------------
419      * G R O U P / R O L E / P E R M I S S I O N  M A N A G E M E N T
420      * -----------------------------------------------------------------------
421      */
422 
423     /***
424      * Retrieves a new Group. It creates
425      * a new Group based on the Services Group implementation. It does not
426      * create a new Group in the system though. Use addGroup for that.
427      * <strong>Not implemented</strong>
428      *
429      * @param groupName The name of the Group to be retrieved.
430      * @return a Group.
431      */
432     public Group getNewGroup(String groupName)
433     {
434         return (Group) new TurbineGroup(groupName);
435     }
436 
437     /***
438      * Retrieves a new Role. It creates
439      * a new Role based on the Services Role implementation. It does not
440      * create a new Role in the system though. Use addRole for that.
441      * <strong>Not implemented</strong>
442      *
443      * @param roleName The name of the Group to be retrieved.
444      * @return a Role.
445      */
446     public Role getNewRole(String roleName)
447     {
448         return (Role) new TurbineRole(roleName);
449     }
450 
451     /***
452      * Retrieves a new Permission. It creates
453      * a new Permission based on the Services Permission implementation. It
454      * does not create a new Permission in the system though. Use create for
455      * that.
456      * <strong>Not implemented</strong>
457      *
458      * @param permissionName The name of the Permission to be retrieved.
459      * @return a Permission
460      */
461     public Permission getNewPermission(String permissionName)
462     {
463         return (Permission) new TurbinePermission(permissionName);
464     }
465 
466     /***
467      * Retrieve a set of Groups that meet the specified Criteria.
468      *
469      * @param criteria Criteria of Group selection.
470      * @return a set of Groups that meet the specified Criteria.
471      * @throws DataBackendException if there is problem with the Backend.
472      */
473     public GroupSet getGroups(Criteria criteria)
474             throws DataBackendException
475     {
476         Vector groups = new Vector();
477 
478         try
479         {
480             DirContext ctx = LDAPUserManager.bindAsAdmin();
481 
482             String baseSearch = LDAPSecurityConstants.getBaseSearch();
483             String filter = "(objectclass=turbineGroup)";
484 
485             /*
486              * Create the default search controls.
487              */
488             SearchControls ctls = new SearchControls();
489 
490             NamingEnumeration answer = ctx.search(baseSearch, filter, ctls);
491 
492             while (answer.hasMore())
493             {
494                 SearchResult sr = (SearchResult) answer.next();
495                 Attributes attribs = sr.getAttributes();
496                 Attribute attr = attribs.get("turbineGroupName");
497 
498                 if (attr != null && attr.get() != null)
499                 {
500                     Group group = getNewGroup(attr.get().toString());
501 
502                     groups.add(group);
503                 }
504             }
505         }
506         catch (NamingException ex)
507         {
508             throw new DataBackendException("NamingException caught", ex);
509         }
510         return new GroupSet(groups);
511     }
512 
513     /*** Get the Roles that a user belongs in a specific group.
514      * @param user The user.
515      * @param group The group
516      * @throws DataBackendException if there is a problem with
517      *     the LDAP service.
518      * @return a RoleSet.
519      */
520     private RoleSet getRoles(User user, Group group)
521             throws DataBackendException
522     {
523         Vector roles = new Vector(0);
524 
525         try
526         {
527             DirContext ctx = LDAPUserManager.bindAsAdmin();
528 
529             String baseSearch = LDAPSecurityConstants.getBaseSearch();
530             String filter = "(& ";
531 
532             filter += "(objectclass=turbineUserGroup)";
533             filter += "(turbineUserUniqueId=" + user.getName() + ")";
534             filter += "(turbineGroupName=" + group.getName() + ")";
535             filter += ")";
536 
537             /*
538              * Create the default search controls.
539              */
540             SearchControls ctls = new SearchControls();
541 
542             ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
543 
544             NamingEnumeration answer = ctx.search(baseSearch, filter, ctls);
545 
546             while (answer.hasMore())
547             {
548                 SearchResult sr = (SearchResult) answer.next();
549                 Attributes attribs = sr.getAttributes();
550                 Attribute attr = attribs.get("turbineRoleName");
551 
552                 if (attr != null)
553                 {
554                     NamingEnumeration values = attr.getAll();
555 
556                     while (values.hasMore())
557                     {
558                         Role role = getNewRole(values.next().toString());
559 
560                         roles.add(role);
561                     }
562                 }
563                 else
564                 {
565                     log.error("Role doesn't have a name");
566                 }
567             }
568         }
569         catch (NamingException ex)
570         {
571             throw new DataBackendException(
572                     "NamingException caught:", ex);
573         }
574 
575         return new RoleSet(roles);
576     }
577 
578     /***
579      * Retrieve a set of Roles that meet the specified Criteria.
580      *
581      * @param criteria Criteria of Roles selection.
582      * @return a set of Roles that meet the specified Criteria.
583      * @throws DataBackendException if there is a problem with the Backend.
584      */
585     public RoleSet getRoles(Criteria criteria) throws DataBackendException
586     {
587         Vector roles = new Vector(0);
588 
589         try
590         {
591             DirContext ctx = LDAPUserManager.bindAsAdmin();
592 
593             String baseSearch = LDAPSecurityConstants.getBaseSearch();
594             String filter = "(objectclass=turbineRole)";
595 
596             /*
597              * Create the default search controls.
598              */
599             SearchControls ctls = new SearchControls();
600 
601             NamingEnumeration answer = ctx.search(baseSearch, filter, ctls);
602 
603             while (answer.hasMore())
604             {
605                 SearchResult sr = (SearchResult) answer.next();
606                 Attributes attribs = sr.getAttributes();
607                 Attribute attr = attribs.get("turbineRoleName");
608 
609                 if (attr != null && attr.get() != null)
610                 {
611                     Role role = getNewRole(attr.get().toString());
612 
613                     roles.add(role);
614                 }
615                 else
616                 {
617                     log.error("Role doesn't have a name");
618                 }
619             }
620         }
621         catch (NamingException ex)
622         {
623             throw new DataBackendException("NamingException caught", ex);
624         }
625 
626         return new RoleSet(roles);
627     }
628 
629     /***
630      * Retrieve a set of Permissions that meet the specified Criteria.
631      *
632      * @param criteria Criteria of Permissions selection.
633      * @return a set of Permissions that meet the specified Criteria.
634      * @throws DataBackendException if there is a problem with the Backend.
635      */
636     public PermissionSet getPermissions(Criteria criteria)
637             throws DataBackendException
638     {
639         Vector permissions = new Vector();
640 
641         try
642         {
643             DirContext ctx = LDAPUserManager.bindAsAdmin();
644 
645             String baseSearch = LDAPSecurityConstants.getBaseSearch();
646             String filter = "(objectClass=turbinePermission)";
647 
648             /*
649              * Create the default search controls.
650              */
651             SearchControls ctls = new SearchControls();
652 
653             NamingEnumeration answer = ctx.search(baseSearch, filter, ctls);
654 
655             while (answer.hasMore())
656             {
657                 SearchResult sr = (SearchResult) answer.next();
658                 Attributes attribs = sr.getAttributes();
659                 Attribute attr = attribs.get("turbinePermissionName");
660 
661                 if (attr != null && attr.get() != null)
662                 {
663                     Permission perm = getNewPermission(attr.get().toString());
664 
665                     permissions.add(perm);
666                 }
667                 else
668                 {
669                     log.error("Permission doesn't have a name");
670                 }
671             }
672         }
673         catch (NamingException ex)
674         {
675             throw new DataBackendException(
676                     "The LDAP server specified is unavailable", ex);
677         }
678         return new PermissionSet(permissions);
679     }
680 
681     /***
682      * Retrieves all permissions associated with a role.
683      *
684      * @param role the role name, for which the permissions are to be retrieved.
685      * @throws DataBackendException if there was an error accessing the backend.
686      * @throws UnknownEntityException if the role is not present.
687      * @return a PermissionSet.
688      */
689     public PermissionSet getPermissions(Role role)
690             throws DataBackendException, UnknownEntityException
691     {
692         Hashtable permissions = new Hashtable();
693 
694         try
695         {
696             DirContext ctx = LDAPUserManager.bindAsAdmin();
697 
698             String baseSearch = LDAPSecurityConstants.getBaseSearch();
699             String filter = "(& ";
700 
701             filter += "(objectClass=turbineRole)";
702             filter += "(turbineRoleName=" + role.getName() + ")";
703             filter += ")";
704 
705             /*
706              * Create the default search controls.
707              */
708             SearchControls ctls = new SearchControls();
709 
710             NamingEnumeration answer = ctx.search(baseSearch, filter, ctls);
711 
712             while (answer.hasMore())
713             {
714                 SearchResult sr = (SearchResult) answer.next();
715                 Attributes attribs = sr.getAttributes();
716                 Attribute attr = attribs.get("turbinePermissionName");
717 
718                 if (attr != null)
719                 {
720                     NamingEnumeration values = attr.getAll();
721 
722                     while (values.hasMore())
723                     {
724                         String permName = values.next().toString();
725                         Permission perm = getNewPermission(permName);
726 
727                         permissions.put(perm.getName(), perm);
728                     }
729                 }
730             }
731         }
732         catch (NamingException ex)
733         {
734             throw new DataBackendException(
735                     "The LDAP server specified is unavailable", ex);
736         }
737         return new PermissionSet(permissions.values());
738     }
739 
740     /***
741      * Stores Group's attributes. The Groups is required to exist in the system.
742      *
743      * @param group The Group to be stored.
744      * @throws DataBackendException if there was an error accessing the backend.
745      * @throws UnknownEntityException if the group does not exist.
746      */
747     public void saveGroup(Group group) throws DataBackendException,
748             UnknownEntityException
749     {
750         // Not implemented yet.
751     }
752 
753     /***
754      * Stores Role's attributes. The Roles is required to exist in the system.
755      *
756      * @param role The Role to be stored.
757      * @throws DataBackendException if there was an error accessing the backend.
758      * @throws UnknownEntityException if the role does not exist.
759      */
760     public void saveRole(Role role) throws DataBackendException,
761             UnknownEntityException
762     {
763         // Not implemented yet.
764     }
765 
766     /***
767      * Stores Permission's attributes. The Permissions is required to exist in
768      * the system.
769      *
770      * @param permission The Permission to be stored.
771      * @throws DataBackendException if there was an error accessing the backend.
772      * @throws UnknownEntityException if the permission does not exist.
773      */
774     public void savePermission(Permission permission)
775             throws DataBackendException, UnknownEntityException
776     {
777         // Not implemented yet.
778     }
779 
780     /***
781      * Creates a new group with specified attributes.
782      * <strong>Not implemented</strong>
783      *
784      * @param group the object describing the group to be created.
785      * @return a new Group object that has id set up properly.
786      * @throws DataBackendException if there was an error accessing the backend.
787      * @throws EntityExistsException if the group already exists.
788      */
789     public synchronized Group addGroup(Group group)
790             throws DataBackendException, EntityExistsException
791     {
792         try
793         {
794             lockExclusive();
795 
796             String groupName = group.getName();
797 
798             if (checkExists(group))
799             {
800                 throw new EntityExistsException(
801                         "Group '" + groupName + "' already exists");
802             }
803 
804             // Make the distinguished name.
805             String dn = "turbineGroupName=" + groupName + ","
806                     + LDAPSecurityConstants.getBaseSearch();
807 
808             // Make the attributes.
809             Attributes attrs = new BasicAttributes();
810 
811             attrs.put(new BasicAttribute("objectClass", "turbineGroup"));
812             attrs.put(new BasicAttribute("turbineGroupName", groupName));
813 
814             // Connect to LDAP.
815             DirContext ctx = LDAPUserManager.bindAsAdmin();
816 
817             // Add the group in LDAP.
818             ctx.bind(dn, null, attrs);
819 
820             // Add the group to system-wide cache.
821             getAllGroups().add(group);
822 
823             return group;
824         }
825         catch (NamingException ex)
826         {
827             throw new DataBackendException("NamingException caught", ex);
828         }
829         finally
830         {
831             unlockExclusive();
832         }
833     }
834 
835     /***
836      * Creates a new role with specified attributes.
837      *
838      * @param role the object describing the role to be created.
839      * @return a new Role object that has id set up properly.
840      * @throws DataBackendException if there was an error accessing the backend.
841      * @throws EntityExistsException if the role already exists.
842      */
843     public synchronized Role addRole(Role role)
844             throws DataBackendException, EntityExistsException
845     {
846         try
847         {
848             lockExclusive();
849 
850             String roleName = role.getName();
851 
852             if (checkExists(role))
853             {
854                 throw new EntityExistsException(
855                         "Role '" + roleName + "' already exists");
856             }
857 
858             // Make the distinguished name.
859             String dn = "turbineRoleName=" + roleName + ","
860                     + LDAPSecurityConstants.getBaseSearch();
861 
862             // Make the attributes.
863             Attributes attrs = new BasicAttributes();
864 
865             attrs.put(new BasicAttribute("objectClass", "turbineRole"));
866             attrs.put(new BasicAttribute("turbineRoleName", roleName));
867 
868             // Connect to LDAP.
869             DirContext ctx = LDAPUserManager.bindAsAdmin();
870 
871             // Add the role in LDAP.
872             ctx.bind(dn, null, attrs);
873 
874             // Add the role to system-wide cache.
875             getAllRoles().add(role);
876 
877             return role;
878         }
879         catch (NamingException ex)
880         {
881             throw new DataBackendException("NamingException caught", ex);
882         }
883         finally
884         {
885             unlockExclusive();
886         }
887     }
888 
889     /***
890      * Creates a new permission with specified attributes.
891      * <strong>Not implemented</strong>
892      *
893      * @param permission the object describing the permission to be created.
894      * @return a new Permission object that has id set up properly.
895      * @throws DataBackendException if there was an error accessing the backend.
896      * @throws EntityExistsException if the permission already exists.
897      */
898     public synchronized Permission addPermission(Permission permission)
899             throws DataBackendException, EntityExistsException
900     {
901         try
902         {
903             lockExclusive();
904 
905             String permName = permission.getName();
906 
907             if (checkExists(permission))
908             {
909                 throw new EntityExistsException(
910                         "Permission '" + permName + "' already exists");
911             }
912 
913             // Make the distinguished name.
914             String dn = "turbinePermissionName=" + permName + ","
915                     + LDAPSecurityConstants.getBaseSearch();
916 
917             // Make the attributes.
918             Attributes attrs = new BasicAttributes();
919 
920             attrs.put(new BasicAttribute("objectClass", "turbinePermission"));
921             attrs.put(new BasicAttribute("turbinePermissionName", permName));
922 
923             DirContext ctx = LDAPUserManager.bindAsAdmin();
924 
925             // Add the permission in LDAP.
926             ctx.bind(dn, null, attrs);
927 
928             // add the permission to system-wide cache
929             getAllPermissions().add(permission);
930 
931             return permission;
932         }
933         catch (NamingException ex)
934         {
935             throw new DataBackendException("NamingException caught", ex);
936         }
937         finally
938         {
939             unlockExclusive();
940         }
941     }
942 
943     /***
944      * Removes a Group from the system.
945      *
946      * @param group object describing group to be removed.
947      * @throws DataBackendException if there was an error accessing the backend.
948      * @throws UnknownEntityException if the group does not exist.
949      */
950     public synchronized void removeGroup(Group group)
951             throws DataBackendException, UnknownEntityException
952     {
953         try
954         {
955             lockExclusive();
956 
957             String groupName = group.getName();
958 
959             if (!checkExists(group))
960             {
961                 throw new UnknownEntityException(
962                         "Group '" + groupName + "' does not exist");
963             }
964 
965             // Make the distinguished name.
966             String dn = "turbineGroupName=" + groupName + ","
967                     + LDAPSecurityConstants.getBaseSearch();
968 
969             DirContext ctx = LDAPUserManager.bindAsAdmin();
970 
971             // Remove the group from LDAP.
972             ctx.unbind(dn);
973 
974             // Remove the group from system-wide cache.
975             getAllGroups().remove(group);
976         }
977         catch (NamingException ex)
978         {
979             throw new DataBackendException("NamingException caught", ex);
980         }
981         finally
982         {
983             unlockExclusive();
984         }
985     }
986 
987     /***
988      * Removes a Role from the system.
989      *
990      * @param role object describing role to be removed.
991      * @throws DataBackendException if there was an error accessing the backend.
992      * @throws UnknownEntityException if the role does not exist.
993      */
994     public synchronized void removeRole(Role role)
995             throws DataBackendException, UnknownEntityException
996     {
997         try
998         {
999             lockExclusive();
1000 
1001             String roleName = role.getName();
1002 
1003             if (!checkExists(role))
1004             {
1005                 throw new UnknownEntityException(
1006                         "Role '" + roleName + "' does not exist");
1007             }
1008 
1009             // Make the distinguished name.
1010             String dn = "turbineRoleName=" + roleName + ","
1011                     + LDAPSecurityConstants.getBaseSearch();
1012 
1013             DirContext ctx = LDAPUserManager.bindAsAdmin();
1014 
1015             // Remove the role from LDAP.
1016             ctx.unbind(dn);
1017 
1018             // Remove the role from system-wide cache.
1019             getAllRoles().remove(role);
1020         }
1021         catch (NamingException ex)
1022         {
1023             throw new DataBackendException("NamingException caught", ex);
1024         }
1025         finally
1026         {
1027             unlockExclusive();
1028         }
1029     }
1030 
1031     /***
1032      * Removes a Permission from the system.
1033      *
1034      * @param permission object describing permission to be removed.
1035      * @throws DataBackendException if there was an error accessing the backend.
1036      * @throws UnknownEntityException if the permission does not exist.
1037      */
1038     public synchronized void removePermission(Permission permission)
1039             throws DataBackendException, UnknownEntityException
1040     {
1041         try
1042         {
1043             lockExclusive();
1044 
1045             String permName = permission.getName();
1046 
1047             if (!checkExists(permission))
1048             {
1049                 throw new UnknownEntityException(
1050                         "Permission '" + permName + "' does not exist");
1051             }
1052 
1053             // Make the distinguished name.
1054             String dn = "turbinePermissionName=" + permName + ","
1055                     + LDAPSecurityConstants.getBaseSearch();
1056 
1057             DirContext ctx = LDAPUserManager.bindAsAdmin();
1058 
1059             // Remove the permission in LDAP.
1060             ctx.unbind(dn);
1061 
1062             // Remove the permission from system-wide cache.
1063             getAllPermissions().remove(permission);
1064         }
1065         catch (NamingException ex)
1066         {
1067             throw new DataBackendException("NamingException caught", ex);
1068         }
1069         finally
1070         {
1071             unlockExclusive();
1072         }
1073     }
1074 
1075     /***
1076      * Renames an existing Group.
1077      *
1078      * @param group object describing the group to be renamed.
1079      * @param name the new name for the group.
1080      * @throws DataBackendException if there was an error accessing the backend.
1081      * @throws UnknownEntityException if the group does not exist.
1082      */
1083     public synchronized void renameGroup(Group group, String name)
1084             throws DataBackendException, UnknownEntityException
1085     {
1086         // Not implemented yet.
1087     }
1088 
1089     /***
1090      * Renames an existing Role.
1091      *
1092      * @param role object describing the role to be renamed.
1093      * @param name the new name for the role.
1094      * @throws DataBackendException if there was an error accessing the backend.
1095      * @throws UnknownEntityException if the role does not exist.
1096      */
1097     public synchronized void renameRole(Role role, String name)
1098             throws DataBackendException, UnknownEntityException
1099     {
1100         // Not implemented yet.
1101     }
1102 
1103     /***
1104      * Renames an existing Permission.
1105      *
1106      * @param permission object describing the permission to be renamed.
1107      * @param name the new name for the permission.
1108      * @throws DataBackendException if there was an error accessing the backend.
1109      * @throws UnknownEntityException if the permission does not exist.
1110      */
1111     public synchronized void renamePermission(Permission permission,
1112                                               String name)
1113             throws DataBackendException, UnknownEntityException
1114     {
1115         // Not implemented yet.
1116     }
1117 
1118     /***
1119      * Revoke all the roles to a user
1120      * @param user the user.
1121      * @throws DataBackendException if there is an error with the data backend.
1122      * @throws UnkownEntityException if the role or a permission is not found.
1123      */
1124     public void revokeAll(User user)
1125             throws DataBackendException, UnknownEntityException
1126     {
1127         Iterator groupsIterator = getAllGroups().iterator();
1128         while (groupsIterator.hasNext())
1129         {
1130             Group group = (Group) groupsIterator.next();
1131             Iterator rolesIterator = getRoles(user, group).iterator();
1132             while (rolesIterator.hasNext())
1133             {
1134                 Role role = (Role) rolesIterator.next();
1135                 revoke(user, group, role);
1136             }
1137         }
1138     }
1139 
1140     /***
1141      * Revoke all the permissions to a role.
1142      * @param role the role.
1143      * @throws DataBackendException if there is an error with the data backend.
1144      * @throws UnkownEntityException if the role or a permission is not found.
1145      */
1146     public void revokeAll(Role role)
1147             throws DataBackendException, UnknownEntityException
1148     {
1149         PermissionSet permissions = getPermissions(role);
1150         Iterator permIterator = permissions.iterator();
1151         while (permIterator.hasNext())
1152         {
1153             Permission perm = (Permission) permIterator.next();
1154             revoke(role, perm);
1155         }
1156     }
1157 
1158     /***
1159      * Revoke all the roles to a group.
1160      * @param group the group.
1161      * @throws DataBackendException if there is an error with the data backend.
1162      * @throws UnkownEntityException if the role or a permission is not found.
1163      */
1164     public void revokeAll(Group group)
1165             throws DataBackendException, UnknownEntityException
1166     {
1167         for (Iterator it = getUserList(new Criteria()).iterator();
1168              it.hasNext();)
1169         {
1170             User user = (User) it.next();
1171             for (Iterator rolesIterator = getRoles(user, group).iterator();
1172                  rolesIterator.hasNext();)
1173             {
1174                 Role role = (Role) rolesIterator.next();
1175                 revoke(user, group, role);
1176             }
1177         }
1178     }
1179 
1180     /***
1181      * Determines if the <code>Role</code> exists in the security system.
1182      *
1183      * @param role a <code>Role</code> value
1184      * @return true if the role exists in the system, false otherwise
1185      * @throws DataBackendException if there is an error with LDAP
1186      */
1187     public boolean checkExists(Role role)
1188             throws DataBackendException
1189     {
1190         RoleSet roleSet = getRoles(new Criteria());
1191 
1192         return roleSet.contains(role);
1193     }
1194 
1195     /***
1196      * Determines if the <code>Group</code> exists in the security system.
1197      *
1198      * @param group a <code>Group</code> value
1199      * @return true if the group exists in the system, false otherwise
1200      * @throws DataBackendException if there is an error with LDAP
1201      */
1202     public boolean checkExists(Group group)
1203             throws DataBackendException
1204     {
1205         GroupSet groupSet = getGroups(new Criteria());
1206 
1207         return groupSet.contains(group);
1208     }
1209 
1210     /***
1211      * Determines if the <code>Permission</code> exists in the security system.
1212      *
1213      * @param permission a <code>Permission</code> value
1214      * @return true if the permission exists in the system, false otherwise
1215      * @throws DataBackendException if there is an error with LDAP
1216      */
1217     public boolean checkExists(Permission permission)
1218             throws DataBackendException
1219     {
1220         PermissionSet permissionSet = getPermissions(new Criteria());
1221 
1222         return permissionSet.contains(permission);
1223     }
1224 }