View Javadoc

1   /* 
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.jetspeed.security.impl;
18  
19  import java.security.AllPermission;
20  import java.security.CodeSource;
21  import java.security.Permission;
22  import java.security.PermissionCollection;
23  import java.security.Permissions;
24  import java.security.Policy;
25  import java.security.Principal;
26  import java.security.ProtectionDomain;
27  import java.util.Arrays;
28  import java.util.List;
29  
30  import org.apache.commons.logging.Log;
31  import org.apache.commons.logging.LogFactory;
32  import org.apache.jetspeed.security.PermissionManager;
33  import org.apache.jetspeed.security.SecurityHelper;
34  import org.apache.jetspeed.security.SecurityPolicies;
35  
36  /***
37   * <p>
38   * Policy implementation using a relational database as persistent datastore.
39   * </p>
40   * <p>
41   * This code was partially inspired from articles from:<br>
42   * <ul>
43   * <li><a href="http://www.ibm.com/developerworks/library/j-jaas/"> Extend JAAS for class
44   * instance-level authorization.</a></li>
45   * <li><a href="http://www.javageeks.com/Papers/JavaPolicy/index.html"> When "java.policy" Just
46   * Isn't Good Enough.</li>
47   * </ul>
48   * </p>
49   * 
50   * @author <a href="mailto:dlestrat@apache.org">David Le Strat</a>
51   */
52  public class RdbmsPolicy extends Policy
53  {
54      private static final Log log = LogFactory.getLog(RdbmsPolicy.class);
55  
56      /***
57       * <p>
58       * InternalPermission Manager Service.
59       * </p>
60       */
61      private PermissionManager pms = null;
62  
63      /***
64       * <p>
65       * Default constructor.
66       * </p>
67       */
68      public RdbmsPolicy(PermissionManager pms)
69      {
70          if (log.isDebugEnabled())
71          {
72              log.debug("RdbmsPolicy constructed.");
73          }
74          this.pms = pms;
75      }
76  
77      /***
78       * @see java.security.Policy#refresh()
79       */
80      public void refresh()
81      {
82  //        if (log.isDebugEnabled())
83  //        {
84  //            log.debug("RdbmsPolicy refresh called.");
85  //        }
86      }
87  
88      /***
89       * <p>
90       * Check that the permission is implied for the protection domain. This will check for
91       * permissions against the configured RDBMS and all {@link SecurityPolicies} configured through
92       * the AuthorizationProvider.
93       * </p>
94       * <p>
95       * The default policy is by default part of the {@link SecurityPolicies} and will only if
96       * configured through assembly.
97       * </p>
98       * 
99       * @see java.security.Policy#implies(java.security.ProtectionDomain, java.security.Permission)
100      */
101     public boolean implies(ProtectionDomain protectionDomain, Permission permission)
102     {
103         Principal[] principals = protectionDomain.getPrincipals();
104         PermissionCollection perms = new Permissions();
105         boolean permImplied = false;
106         if ((null != principals) && (principals.length > 0))
107         {
108             // We need to authorize java permissions.
109             // Without this check, we get a ClassCircularityError in Tomcat.
110             if (permission.getClass().getName().startsWith("java"))
111             {
112                 perms.add(new AllPermission());
113             }
114             else
115             {
116 //                if (log.isDebugEnabled())
117 //                {
118 //                    log.debug("Implying permission [class, " + permission.getClass().getName() + "], " + "[name, "
119 //                            + permission.getName() + "], " + "[actions, " + permission.getActions() + "] for: ");
120 //                    log.debug("\tCodeSource:" + protectionDomain.getCodeSource().getLocation().getPath());
121 //                    for (int i = 0; i < principals.length; i++)
122 //                    {
123 //                        log.debug("\tPrincipal[" + i + "]: [name, " + principals[i].getName() + "], [class, "
124 //                                + principals[i].getClass() + "]");
125 //                    }
126 //                }
127                 perms = pms.getPermissions(Arrays.asList(principals));
128             }
129         }
130         else
131         {
132             // No principal is returned from the subject.
133             // For security check, be sure to use doAsPrivileged(theSubject, anAction, null)...
134             // We grant access when no principal is associated to the subject.
135             perms.add(new AllPermission());
136         }
137         if (null != perms)
138         {
139             permImplied = perms.implies(permission);
140         }
141         return permImplied;
142     }
143 
144     /***
145      * @see java.security.Policy#getPermissions(java.security.ProtectionDomain)
146      */
147     public PermissionCollection getPermissions(ProtectionDomain domain)
148     {
149         PermissionCollection otherPerms = new Permissions();
150         if (null != domain)
151         {
152             otherPerms = getPermissions(domain.getCodeSource());
153         }
154         return otherPerms;
155     }
156 
157     /***
158      * <p>
159      * The RdbmsPolicy does not protect code source per say, but will return the protected code
160      * source from the other configured policies.
161      * </p>
162      * 
163      * @see java.security.Policy#getPermissions(java.security.CodeSource)
164      */
165     public PermissionCollection getPermissions(CodeSource codeSource)
166     {
167 //        if (log.isDebugEnabled())
168 //        {
169 //            log.debug("getPermissions called for '" + codeSource + "'.");
170 //        }
171         PermissionCollection otherPerms = getOtherPoliciesPermissions(codeSource);
172 
173         return otherPerms;
174     }
175 
176     /***
177      * <p>
178      * Gets all the permissions that should be enforced through the other policies configured.
179      * </p>
180      * 
181      * @param codeSource The CodeSource.
182      * @return A collection of permissions as a {@link PermissionCollection}
183      */
184     private PermissionCollection getOtherPoliciesPermissions(CodeSource codeSource)
185     {
186 //        if (log.isDebugEnabled())
187 //        {
188 //            log.debug("Checking other policies permissions.");
189 //        }
190         log.debug("CodeSource: " + codeSource.getLocation().getPath());
191 
192         List securityPolicies = SecurityPolicies.getInstance().getUsedPolicies();
193         PermissionCollection otherPerms = new Permissions();
194         for (int i = 0; i < securityPolicies.size(); i++)
195         {
196             Policy currPolicy = (Policy) securityPolicies.get(i);
197             if (!currPolicy.getClass().equals(getClass()))
198             {
199                 if (log.isDebugEnabled())
200                 {
201                     log.debug("Checking policy: " + currPolicy.getClass().getName());
202                 }
203                 PermissionCollection currPerms = currPolicy.getPermissions(codeSource);
204                 SecurityHelper.addPermissions(otherPerms, currPerms);
205             }
206         }
207 
208         // Return the default permission collection.
209         return otherPerms;
210     }
211 
212 }