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    
018    package org.apache.geronimo.security.jacc.mappingprovider;
019    
020    import java.security.Permission;
021    import java.security.PermissionCollection;
022    import java.security.Permissions;
023    import java.security.Principal;
024    import java.security.ProtectionDomain;
025    import java.util.Enumeration;
026    import java.util.HashMap;
027    import java.util.Map;
028    import java.util.Set;
029    
030    import javax.security.jacc.PolicyContextException;
031    
032    
033    /**
034     * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
035     */
036    public class PolicyConfigurationGeneric implements GeronimoPolicyConfiguration {
037        final static int OPEN = 1;
038        final static int IN_SERVICE = 2;
039        final static int DELETED = 3;
040    
041        private final String contextID;
042        private int state;
043        private final HashMap<String, Permissions> rolePermissionsMap = new HashMap<String, Permissions>();
044        private final HashMap<Principal, Set<String>> principalRoleMapping = new HashMap<Principal, Set<String>>();
045        private Permissions unchecked = null;
046        private Permissions excluded = null;
047    
048        private final HashMap<Principal, Permissions> principalPermissionsMap = new HashMap<Principal, Permissions>();
049    
050        PolicyConfigurationGeneric(String contextID) {
051            this.contextID = contextID;
052            this.state = OPEN;
053        }
054    
055        public String getContextID() throws PolicyContextException {
056            return contextID;
057        }
058    
059        public boolean implies(ProtectionDomain domain, Permission permission) {
060    
061            if (excluded != null && excluded.implies(permission)) return false;
062    
063            if (unchecked != null && unchecked.implies(permission)) return true;
064    
065            Principal[] principals = domain.getPrincipals();
066            if (principals.length == 0) return false;
067    
068            for (Principal principal : principals) {
069                Permissions permissions = (Permissions) principalPermissionsMap.get(principal);
070    
071                if (permissions != null && permissions.implies(permission)) return true;
072            }
073    
074            return false;
075        }
076    
077        public void setPrincipalRoleMapping(Map principalRoleMap) throws PolicyContextException {
078            principalRoleMapping.clear();
079            principalRoleMapping.putAll(principalRoleMap);
080        }
081    
082        public void addToRole(String roleName, PermissionCollection permissions) throws PolicyContextException {
083            if (state != OPEN) throw new UnsupportedOperationException("Not in an open state");
084    
085            Enumeration e = permissions.elements();
086            while (e.hasMoreElements()) {
087                addToRole(roleName, (Permission) e.nextElement());
088            }
089        }
090    
091        public void addToRole(String roleName, Permission permission) throws PolicyContextException {
092            if (state != OPEN) throw new UnsupportedOperationException("Not in an open state");
093    
094            Permissions permissions = rolePermissionsMap.get(roleName);
095            if (permissions == null) {
096                permissions = new Permissions();
097                rolePermissionsMap.put(roleName, permissions);
098            }
099            permissions.add(permission);
100        }
101    
102        public void addToUncheckedPolicy(PermissionCollection permissions) throws PolicyContextException {
103            if (state != OPEN) throw new UnsupportedOperationException("Not in an open state");
104    
105            Enumeration e = permissions.elements();
106            while (e.hasMoreElements()) {
107                addToUncheckedPolicy((Permission) e.nextElement());
108            }
109        }
110    
111        public void addToUncheckedPolicy(Permission permission) throws PolicyContextException {
112            if (state != OPEN) throw new UnsupportedOperationException("Not in an open state");
113    
114            if (unchecked == null) unchecked = new Permissions();
115    
116            unchecked.add(permission);
117        }
118    
119        public void addToExcludedPolicy(PermissionCollection permissions) throws PolicyContextException {
120            if (state != OPEN) throw new UnsupportedOperationException("Not in an open state");
121    
122            Enumeration e = permissions.elements();
123            while (e.hasMoreElements()) {
124                addToExcludedPolicy((Permission) e.nextElement());
125            }
126        }
127    
128        public void addToExcludedPolicy(Permission permission) throws PolicyContextException {
129            if (state != OPEN) throw new UnsupportedOperationException("Not in an open state");
130    
131            if (excluded == null) excluded = new Permissions();
132    
133            excluded.add(permission);
134        }
135    
136        public void removeRole(String roleName) throws PolicyContextException {
137            if (state != OPEN) throw new UnsupportedOperationException("Not in an open state");
138    
139            rolePermissionsMap.remove(roleName);
140        }
141    
142        public void removeUncheckedPolicy() throws PolicyContextException {
143            if (state != OPEN) throw new UnsupportedOperationException("Not in an open state");
144    
145            unchecked = null;
146        }
147    
148        public void removeExcludedPolicy() throws PolicyContextException {
149            if (state != OPEN) throw new UnsupportedOperationException("Not in an open state");
150    
151            excluded = null;
152        }
153    
154        public void linkConfiguration(javax.security.jacc.PolicyConfiguration link) throws PolicyContextException {
155            if (state != OPEN) throw new UnsupportedOperationException("Not in an open state");
156        }
157    
158        public void delete() throws PolicyContextException {
159            state = DELETED;
160        }
161    
162        public void commit() throws PolicyContextException {
163            if (state != OPEN) throw new UnsupportedOperationException("Not in an open state");
164    
165            for (Map.Entry<Principal, Set<String>> principalEntry : principalRoleMapping.entrySet()) {
166                Principal principal = principalEntry.getKey();
167                Permissions principalPermissions = principalPermissionsMap.get(principal);
168    
169                if (principalPermissions == null) {
170                    principalPermissions = new Permissions();
171                    principalPermissionsMap.put(principal, principalPermissions);
172                }
173    
174                Set<String> roleSet = principalEntry.getValue();
175                for (String role : roleSet) {
176                    Permissions permissions = rolePermissionsMap.get(role);
177                    if (permissions == null) continue;
178                    for (Enumeration rolePermissions = permissions.elements(); rolePermissions.hasMoreElements();) {
179                        principalPermissions.add((Permission) rolePermissions.nextElement());
180                    }
181                }
182    
183            }
184            state = IN_SERVICE;
185        }
186    
187        public boolean inService() throws PolicyContextException {
188            return (state == IN_SERVICE);
189        }
190    
191        //TODO I have no idea what side effects this might have, but it's needed in some form from GeronimoPolicyConfigurationFactory.
192        //see JACC spec 1.0 section 3.1.1.1 discussion of in service and deleted.
193        //spec p. 31 3.1.7 on the effects of remove:
194        //If the getPolicyConfiguration method  is used, the value true should be passed as the second
195        //  argument to cause the  corresponding policy statements to be deleted from the context.
196        public void open(boolean remove) {
197            if (remove) {
198                rolePermissionsMap.clear();
199                principalRoleMapping.clear();
200                unchecked = null;
201                excluded = null;
202                principalPermissionsMap.clear();
203            }
204            state = OPEN;
205        }
206    
207        int getState() {
208            return state;
209        }
210    }