001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.jetspeed.security.impl;
018:
019: import java.security.AllPermission;
020: import java.security.CodeSource;
021: import java.security.Permission;
022: import java.security.PermissionCollection;
023: import java.security.Permissions;
024: import java.security.Policy;
025: import java.security.Principal;
026: import java.security.ProtectionDomain;
027: import java.util.Arrays;
028: import java.util.List;
029:
030: import org.apache.commons.logging.Log;
031: import org.apache.commons.logging.LogFactory;
032: import org.apache.jetspeed.security.PermissionManager;
033: import org.apache.jetspeed.security.SecurityHelper;
034: import org.apache.jetspeed.security.SecurityPolicies;
035:
036: /**
037: * <p>
038: * Policy implementation using a relational database as persistent datastore.
039: * </p>
040: * <p>
041: * This code was partially inspired from articles from:<br>
042: * <ul>
043: * <li><a href="http://www.ibm.com/developerworks/library/j-jaas/"> Extend JAAS for class
044: * instance-level authorization.</a></li>
045: * <li><a href="http://www.javageeks.com/Papers/JavaPolicy/index.html"> When "java.policy" Just
046: * Isn't Good Enough.</li>
047: * </ul>
048: * </p>
049: *
050: * @author <a href="mailto:dlestrat@apache.org">David Le Strat</a>
051: */
052: public class RdbmsPolicy extends Policy {
053: private static final Log log = LogFactory.getLog(RdbmsPolicy.class);
054:
055: /**
056: * <p>
057: * InternalPermission Manager Service.
058: * </p>
059: */
060: private PermissionManager pms = null;
061:
062: /**
063: * <p>
064: * Default constructor.
065: * </p>
066: */
067: public RdbmsPolicy(PermissionManager pms) {
068: if (log.isDebugEnabled()) {
069: log.debug("RdbmsPolicy constructed.");
070: }
071: this .pms = pms;
072: }
073:
074: /**
075: * @see java.security.Policy#refresh()
076: */
077: public void refresh() {
078: // if (log.isDebugEnabled())
079: // {
080: // log.debug("RdbmsPolicy refresh called.");
081: // }
082: }
083:
084: /**
085: * <p>
086: * Check that the permission is implied for the protection domain. This will check for
087: * permissions against the configured RDBMS and all {@link SecurityPolicies} configured through
088: * the AuthorizationProvider.
089: * </p>
090: * <p>
091: * The default policy is by default part of the {@link SecurityPolicies} and will only if
092: * configured through assembly.
093: * </p>
094: *
095: * @see java.security.Policy#implies(java.security.ProtectionDomain, java.security.Permission)
096: */
097: public boolean implies(ProtectionDomain protectionDomain,
098: Permission permission) {
099: Principal[] principals = protectionDomain.getPrincipals();
100: PermissionCollection perms = new Permissions();
101: boolean permImplied = false;
102: if ((null != principals) && (principals.length > 0)) {
103: // We need to authorize java permissions.
104: // Without this check, we get a ClassCircularityError in Tomcat.
105: if (permission.getClass().getName().startsWith("java")) {
106: perms.add(new AllPermission());
107: } else {
108: // if (log.isDebugEnabled())
109: // {
110: // log.debug("Implying permission [class, " + permission.getClass().getName() + "], " + "[name, "
111: // + permission.getName() + "], " + "[actions, " + permission.getActions() + "] for: ");
112: // log.debug("\tCodeSource:" + protectionDomain.getCodeSource().getLocation().getPath());
113: // for (int i = 0; i < principals.length; i++)
114: // {
115: // log.debug("\tPrincipal[" + i + "]: [name, " + principals[i].getName() + "], [class, "
116: // + principals[i].getClass() + "]");
117: // }
118: // }
119: perms = pms.getPermissions(Arrays.asList(principals));
120: }
121: } else {
122: // No principal is returned from the subject.
123: // For security check, be sure to use doAsPrivileged(theSubject, anAction, null)...
124: // We grant access when no principal is associated to the subject.
125: perms.add(new AllPermission());
126: }
127: if (null != perms) {
128: permImplied = perms.implies(permission);
129: }
130: return permImplied;
131: }
132:
133: /**
134: * @see java.security.Policy#getPermissions(java.security.ProtectionDomain)
135: */
136: public PermissionCollection getPermissions(ProtectionDomain domain) {
137: PermissionCollection otherPerms = new Permissions();
138: if (null != domain) {
139: otherPerms = getPermissions(domain.getCodeSource());
140: }
141: return otherPerms;
142: }
143:
144: /**
145: * <p>
146: * The RdbmsPolicy does not protect code source per say, but will return the protected code
147: * source from the other configured policies.
148: * </p>
149: *
150: * @see java.security.Policy#getPermissions(java.security.CodeSource)
151: */
152: public PermissionCollection getPermissions(CodeSource codeSource) {
153: // if (log.isDebugEnabled())
154: // {
155: // log.debug("getPermissions called for '" + codeSource + "'.");
156: // }
157: PermissionCollection otherPerms = getOtherPoliciesPermissions(codeSource);
158:
159: return otherPerms;
160: }
161:
162: /**
163: * <p>
164: * Gets all the permissions that should be enforced through the other policies configured.
165: * </p>
166: *
167: * @param codeSource The CodeSource.
168: * @return A collection of permissions as a {@link PermissionCollection}
169: */
170: private PermissionCollection getOtherPoliciesPermissions(
171: CodeSource codeSource) {
172: // if (log.isDebugEnabled())
173: // {
174: // log.debug("Checking other policies permissions.");
175: // }
176: log.debug("CodeSource: " + codeSource.getLocation().getPath());
177:
178: List securityPolicies = SecurityPolicies.getInstance()
179: .getUsedPolicies();
180: PermissionCollection otherPerms = new Permissions();
181: for (int i = 0; i < securityPolicies.size(); i++) {
182: Policy currPolicy = (Policy) securityPolicies.get(i);
183: if (!currPolicy.getClass().equals(getClass())) {
184: if (log.isDebugEnabled()) {
185: log.debug("Checking policy: "
186: + currPolicy.getClass().getName());
187: }
188: PermissionCollection currPerms = currPolicy
189: .getPermissions(codeSource);
190: SecurityHelper.addPermissions(otherPerms, currPerms);
191: }
192: }
193:
194: // Return the default permission collection.
195: return otherPerms;
196: }
197:
198: }
|