View Javadoc

1   /*
2    * Copyright 2000-2001,2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
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.Vector;
22  import javax.naming.directory.BasicAttributes;
23  import javax.servlet.ServletConfig;
24  import org.apache.jetspeed.om.security.Permission;
25  import org.apache.jetspeed.om.security.ldap.LDAPPermission;
26  import org.apache.jetspeed.om.security.ldap.LDAPRole;
27  import org.apache.jetspeed.services.JetspeedLDAP;
28  import org.apache.jetspeed.services.JetspeedSecurity;
29  import org.apache.jetspeed.services.ldap.LDAPURL;
30  import org.apache.jetspeed.services.rundata.JetspeedRunData;
31  import org.apache.jetspeed.services.rundata.JetspeedRunDataService;
32  import org.apache.jetspeed.services.security.JetspeedSecurityCache;
33  import org.apache.jetspeed.services.security.JetspeedSecurityException;
34  import org.apache.jetspeed.services.security.JetspeedSecurityService;
35  import org.apache.jetspeed.services.security.PermissionException;
36  import org.apache.jetspeed.services.security.PermissionManagement;
37  import org.apache.turbine.services.InitializationException;
38  import org.apache.turbine.services.TurbineBaseService;
39  import org.apache.turbine.services.TurbineServices;
40  import org.apache.turbine.services.resources.ResourceService;
41  import org.apache.turbine.services.rundata.RunDataService;
42  
43  /***
44   *
45   * @author <a href="mailto:ender@kilicoglu.nom.tr">Ender KILICOGLU</a>
46   * @author <a href="mailto:sami.leino@netorek.fi">Sami Leino</a>
47   *
48   * @version $Id: LDAPPermissionManagement.java,v 1.6 2004/02/23 03:52:33 jford Exp $ 
49   * 
50   */
51  public class LDAPPermissionManagement  extends TurbineBaseService
52                                     implements PermissionManagement
53  {
54  	// Constants
55      private final static String CASCADE_DELETE          = "programmatic.cascade.delete";
56      private final static String CACHING_ENABLE          = "caching.enable";
57      private final static boolean DEFAULT_CASCADE_DELETE = true;
58      private final static boolean DEFAULT_CACHING_ENABLE = true;
59      private final static String[] ATTRS                 = { "ou", "uid", "permissionname" };
60  
61  	// Instance variables
62      private JetspeedRunDataService runDataService       = null;
63      private boolean cascadeDelete                       = false;
64      private boolean cachingEnable                       = false;
65  
66      ///////////////////////////////////////////////////////////////////////////
67      // Permission Management Interfaces
68      ///////////////////////////////////////////////////////////////////////////
69  
70      /***
71       * Retrieves all <code>Permission</code>s for a given roleName principal.
72       *
73       * The security service may optionally check the current user context
74       * to determine if the requestor has permission to perform this action.
75       *
76       * @param roleName a role name identity to be retrieved.
77       * @return Iterator over all permissions associated to the role principal.
78       * @exception PermissionException when the security provider has a general failure.
79       * @exception InsufficientPrivilegeException when the requestor is denied due to insufficient privilege
80       */
81      public Iterator getPermissions(String roleName)
82          throws JetspeedSecurityException
83      {
84          Vector perms = new Vector();
85          BasicAttributes attr= new BasicAttributes();
86          LDAPRole role;
87          LDAPPermission permission;
88          Vector userurls;
89  
90          try
91          {
92              if (cachingEnable)
93              {
94                  Iterator iterator = JetspeedSecurityCache.getPermissions(roleName);
95                  if (iterator != null)
96                  {
97                      return iterator;
98                  }
99              }
100 
101             userurls = JetspeedLDAP.search(JetspeedLDAP.buildURL("ou=roles"),
102                        "(&(uid=" + roleName + ")(objectclass=jetspeedrole))", ATTRS, true);
103 
104             if (userurls.size() > 0)
105             {
106                 role = new LDAPRole((LDAPURL) ((Vector)userurls.elementAt(0)).firstElement());
107                 for (Enumeration enum= role.getRolePermissions().elements();enum.hasMoreElements();)
108                 {
109                     permission = new LDAPPermission((String)enum.nextElement(), false);
110                     perms.add(permission);
111                 }
112             }
113         }
114         catch(Exception e)
115         {
116             throw new PermissionException("Failed to retrieve permissions ", e);
117         }
118 
119         return perms.iterator();
120     }
121 
122     /***
123      * Retrieves all <code>Permission</code>s.
124      *
125      * The security service may optionally check the current user context
126      * to determine if the requestor has permission to perform this action.
127      *
128      * @return Iterator over all permissions.
129      * @exception PermissionException when the security provider has a general failure.
130      * @exception InsufficientPrivilegeException when the requestor is denied due to insufficient privilege
131      */
132     public Iterator getPermissions()
133         throws JetspeedSecurityException
134 
135     {
136         BasicAttributes attr= new BasicAttributes();
137         Vector permissions = new Vector();
138         Vector permissionurls;
139  
140         try
141         {
142             permissionurls = JetspeedLDAP.search(JetspeedLDAP.buildURL("ou=permissions"),
143                              "(objectclass=jetspeedpermission)", ATTRS, true);
144 
145             if (permissionurls.size() > 0)
146             {
147                 for (Enumeration enum = permissionurls.elements();enum.hasMoreElements() ;)
148                 {
149                     permissions.add(new LDAPPermission((LDAPURL) (((Vector)enum.nextElement()).firstElement())));
150                 }
151             }
152             else
153             {
154                 throw new PermissionException("No permission ");
155             }
156         }
157         catch(Exception e)
158         {
159             throw new PermissionException("Failed to retrieve permissions ", e);
160         }
161         return permissions.iterator();
162     }
163 
164     /***
165      * Adds a <code>Permission</code> into permanent storage.
166      *
167      * The security service may optionally check the current user context
168      * to determine if the requestor has permission to perform this action.
169      *
170      * @exception PermissionException when the security provider has a general failure.
171      * @exception InsufficientPrivilegeException when the requestor is denied due to insufficient privilege
172      */
173     public void addPermission(Permission permission)
174         throws JetspeedSecurityException
175     {
176         if(permissionExists(permission.getName()))
177         {
178             throw new PermissionException("The permission '" +
179                 permission.getName() + "' already exists");
180         }
181         try
182         {
183             new LDAPPermission(permission.getName(), true).update(true);
184         }
185         catch(Exception e)
186         {
187             throw new PermissionException("Failed to create permission '" +
188                 permission.getName() + "'", e);
189         }
190     }
191 
192 
193     /***
194      * Saves a <code>Permission</code> into permanent storage.
195      *
196      * The security service may optionally check the current user context
197      * to determine if the requestor has permission to perform this action.
198      *
199      * @exception PermissionException when the security provider has a general failure.
200      * @exception InsufficientPrivilegeException when the requestor is denied due to insufficient privilege
201      */
202     public void savePermission(Permission permission)
203         throws JetspeedSecurityException
204     {
205     }
206 
207     /***
208      * Removes a <code>Permission</code> from the permanent store.
209      *
210      * The security service may optionally check the current user context
211      * to determine if the requestor has permission to perform this action.
212      *
213      * @param permissionName the principal identity of the permission to be retrieved.
214      * @exception PermissionException when the security provider has a general failure.
215      * @exception InsufficientPrivilegeException when the requestor is denied due to insufficient privilege
216      */
217     public void removePermission(String permissionName)
218         throws JetspeedSecurityException
219     {
220         try
221         {
222             LDAPPermission permission = new LDAPPermission(permissionName,false);
223             JetspeedLDAP.deleteEntry(permission.getldapurl());
224 
225             if(cascadeDelete)
226             {
227             }
228 
229             if (cachingEnable)
230             {
231                 JetspeedSecurityCache.removeAllPermissions(permissionName);
232             }
233         }
234         catch(Exception e)
235         {
236             throw new PermissionException("Failed to remove permission '" +
237                 permissionName + "'", e);
238         }
239     }
240 
241     /***
242      * Grants a permission to a role.
243      *
244      * The security service may optionally check the current user context
245      * to determine if the requestor has permission to perform this action.
246      *
247      * @param roleName grant a permission to this role.
248 
249      * @param permissionName the permission to grant to the role.
250      * @exception PermissionException when the security provider has a general failure retrieving permissions.
251      * @exception InsufficientPrivilegeException when the requestor is denied due to insufficient privilege
252      */
253     public void grantPermission(String roleName, String permissionName)
254         throws JetspeedSecurityException
255     {
256         BasicAttributes attr = new BasicAttributes();
257         LDAPRole role;
258         LDAPPermission permission;
259 
260         try
261         {
262             role = (LDAPRole)JetspeedSecurity.getRole(roleName);
263             permission = (LDAPPermission)JetspeedSecurity.getPermission(permissionName);
264 
265             role.addRolePermissions(permissionName);
266             role.update(false);
267 
268             if (cachingEnable)
269             {
270                 JetspeedSecurityCache.addPermission(roleName, permission);
271             }
272         }
273         catch(Exception e)
274         {
275             throw new PermissionException("Grant permission '" + permissionName + "' to role '" + roleName + "' failed: ", e);
276         }
277     }
278 
279     /***
280      * Revokes a permission from a role.
281      *
282      * The security service may optionally check the current user context
283      * to determine if the requestor has permission to perform this action.
284      *
285      * @param roleName grant a permission to this role.
286      * @param permissionName the permission to grant to the role.
287      * @exception PermissionException when the security provider has a general failure retrieving permissions.
288      * @exception InsufficientPrivilegeException when the requestor is denied due to insufficient privilege
289      */
290     public void revokePermission(String roleName, String permissionName)
291         throws JetspeedSecurityException
292     {
293         BasicAttributes attr= new BasicAttributes();
294         LDAPRole role;
295         Vector userurls;
296 
297         try
298         {
299             userurls = JetspeedLDAP.search(JetspeedLDAP.buildURL("ou=roles"),
300                        "(&(uid="+ roleName+")(objectclass=jetspeedrole))", ATTRS, true);
301 
302             if (userurls.size() == 0)
303             {
304             	throw new PermissionException("Role '" + roleName + "' does not exist!");
305             }
306             else
307             {
308                 role = new LDAPRole((LDAPURL) ((Vector)userurls.elementAt(0)).firstElement());
309                 role.getRolePermissions().remove(permissionName);
310                 role.update(false);
311 
312                 if (cachingEnable)
313                 {
314                     JetspeedSecurityCache.removePermission(roleName, permissionName);
315                 }
316             }
317         }
318         catch(Exception e)
319         {
320             throw new PermissionException("Revoke permission '" + permissionName + "' to role '" + roleName + "' failed: ", e);
321        }
322     }
323 
324     /***
325      * Checks for the relationship of role has a permission. Returns true when the role has the given permission.
326      *
327      * The security service may optionally check the current user context
328      * to determine if the requestor has permission to perform this action.
329      *
330      * @param roleName grant a permission to this role.
331      * @param permissionName the permission to grant to the role.
332      * @exception PermissionException when the security provider has a general failure retrieving permissions.
333      * @exception InsufficientPrivilegeException when the requestor is denied due to insufficient privilege
334      */
335     public boolean hasPermission(String roleName, String permissionName)
336         throws JetspeedSecurityException
337     {
338         BasicAttributes attr= new BasicAttributes();
339         LDAPRole role;
340         Vector userurls;
341 
342         try
343         {
344             if (cachingEnable)
345             {
346                 return JetspeedSecurityCache.hasPermission(roleName, permissionName);
347             }
348 
349             userurls = JetspeedLDAP.search(JetspeedLDAP.buildURL("ou=roles"),
350                        "(&(uid="+ roleName+")(objectclass=jetspeedrole))", ATTRS, true);
351 
352             if (userurls.size() > 0)
353             {
354                 role = new LDAPRole((LDAPURL) ((Vector)userurls.elementAt(0)).firstElement());
355                 return role.permissionExists(permissionName);
356             }
357         }
358         catch(Exception e)
359         {
360             throw new PermissionException("Grant permission '" + permissionName + "' to role '" + roleName + "' failed: ", e);
361         }
362         return false;
363     }
364 
365     /***
366      * Retrieves a single <code>Permission</code> for a given permissionName principal.
367      *
368      * The security service may optionally check the current user context
369      * to determine if the requestor has permission to perform this action.
370      *
371      * @param permissionName a permission principal identity to be retrieved.
372      * @return Permission the permission record retrieved.
373      * @exception PermissionException when the security provider has a general failure.
374      * @exception InsufficientPrivilegeException when the requestor is denied due to insufficient privilege
375      */
376     public Permission getPermission(String permissionName)
377         throws JetspeedSecurityException
378     {
379         if (permissionExists(permissionName))
380         {
381             return new LDAPPermission(permissionName, false);
382         }
383         else
384         {
385             throw new PermissionException("Unknown permission '" + permissionName + "'");
386         }
387     }
388 
389     ///////////////////////////////////////////////////////////////////////////
390     // Internal
391     ///////////////////////////////////////////////////////////////////////////
392 
393     protected JetspeedRunData getRunData()
394      {
395          JetspeedRunData rundata = null;
396 
397          if (this.runDataService != null)
398          {
399              rundata = this.runDataService.getCurrentRunData();
400          }
401 
402          return rundata;
403      }
404 
405     /***
406      * Check whether a specified permission exists.
407      *
408      * The login name is used for looking up the account.
409      *
410      * @param permissionName the name of the permission to check for existence.
411      * @return true if the specified account exists
412      * @throws PermissionException if there was a general db access error
413      *
414      */
415     protected boolean permissionExists(String permissionName)
416         throws PermissionException
417     {
418         BasicAttributes attr= new BasicAttributes();
419         Vector permissionurls;
420 
421         try
422         {
423             permissionurls = JetspeedLDAP.search(JetspeedLDAP.buildURL("ou=permissions"),
424                              "(&(uid=" + permissionName + ")(objectclass=jetspeedpermission))", ATTRS, true);
425 
426             if (permissionurls.size() > 0)
427             {
428                 return true;
429             }
430             else
431             {
432                 return false;
433             }
434         }
435         catch(Exception e)
436         {
437             e.printStackTrace();
438             throw new PermissionException("Failed to retrieve permission ", e);
439         }
440     }
441 
442     ///////////////////////////////////////////////////////////////////////////
443     // Service Init
444     ///////////////////////////////////////////////////////////////////////////
445 
446     /***
447      * This is the early initialization method called by the
448      * Turbine <code>Service</code> framework
449      * @param conf The <code>ServletConfig</code>
450      * @exception throws a <code>InitializationException</code> if the service
451      * fails to initialize
452      */
453     public synchronized void init(ServletConfig conf)
454         throws InitializationException
455     {
456         if (getInit()) return;
457 
458         super.init(conf);
459 
460         // get configuration parameters from Jetspeed Resources
461         ResourceService serviceConf = ((TurbineServices)TurbineServices.getInstance())
462                                                      .getResources(JetspeedSecurityService.SERVICE_NAME);
463 
464         this.runDataService =
465            (JetspeedRunDataService)TurbineServices.getInstance()
466                .getService(RunDataService.SERVICE_NAME);
467 
468         cascadeDelete = serviceConf.getBoolean( CASCADE_DELETE, DEFAULT_CASCADE_DELETE );
469         cachingEnable = serviceConf.getBoolean( CACHING_ENABLE, cachingEnable );
470         setInit(true);
471      }
472 }