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