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.geronimo.security.jacc;
018    
019    import java.security.Permission;
020    import java.security.PermissionCollection;
021    import java.security.Policy;
022    import java.util.Enumeration;
023    import java.util.HashMap;
024    import java.util.Map;
025    
026    import javax.security.auth.Subject;
027    import javax.security.auth.login.LoginException;
028    import javax.security.jacc.PolicyConfiguration;
029    import javax.security.jacc.PolicyConfigurationFactory;
030    import javax.security.jacc.PolicyContextException;
031    
032    import org.apache.geronimo.gbean.GBeanInfo;
033    import org.apache.geronimo.gbean.GBeanInfoBuilder;
034    import org.apache.geronimo.gbean.GBeanLifecycle;
035    import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
036    import org.apache.geronimo.security.ContextManager;
037    import org.apache.geronimo.security.IdentificationPrincipal;
038    import org.apache.geronimo.security.SubjectId;
039    import org.apache.geronimo.security.credentialstore.CredentialStore;
040    import org.apache.geronimo.security.deploy.SubjectInfo;
041    
042    /**
043     * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
044     */
045    public class ApplicationPolicyConfigurationManager implements GBeanLifecycle, RunAsSource {
046    
047        private final Map<String, PolicyConfiguration> contextIdToPolicyConfigurationMap = new HashMap<String, PolicyConfiguration>();
048        private final Map<String, Subject> roleDesignates = new HashMap<String, Subject>();
049        private final Subject defaultSubject;
050        private final PrincipalRoleMapper principalRoleMapper;
051    
052        public ApplicationPolicyConfigurationManager(Map<String, ComponentPermissions> contextIdToPermissionsMap, SubjectInfo defaultSubjectInfo, Map<String, SubjectInfo> roleDesignates, ClassLoader cl, CredentialStore credentialStore, PrincipalRoleMapper principalRoleMapper) throws PolicyContextException, ClassNotFoundException, LoginException {
053            if (credentialStore == null && (!roleDesignates.isEmpty() || defaultSubjectInfo != null)) {
054                throw new NullPointerException("No CredentialStore supplied to resolve default and run-as subjects");
055            }
056            this.principalRoleMapper = principalRoleMapper;
057            Thread currentThread = Thread.currentThread();
058            ClassLoader oldClassLoader = currentThread.getContextClassLoader();
059            currentThread.setContextClassLoader(cl);
060            PolicyConfigurationFactory policyConfigurationFactory;
061            try {
062                policyConfigurationFactory = PolicyConfigurationFactory.getPolicyConfigurationFactory();
063            } finally {
064                currentThread.setContextClassLoader(oldClassLoader);
065            }
066    
067            for (Map.Entry<String, ComponentPermissions> entry : contextIdToPermissionsMap.entrySet()) {
068                String contextID = entry.getKey();
069                ComponentPermissions componentPermissions = entry.getValue();
070    
071                PolicyConfiguration policyConfiguration = policyConfigurationFactory.getPolicyConfiguration(contextID, true);
072                contextIdToPolicyConfigurationMap.put(contextID, policyConfiguration);
073                policyConfiguration.addToExcludedPolicy(componentPermissions.getExcludedPermissions());
074                policyConfiguration.addToUncheckedPolicy(componentPermissions.getUncheckedPermissions());
075                for (Map.Entry<String, PermissionCollection> roleEntry : componentPermissions.getRolePermissions().entrySet()) {
076                    String roleName = roleEntry.getKey();
077                    PermissionCollection rolePermissions = roleEntry.getValue();
078                    for (Enumeration permissions = rolePermissions.elements(); permissions.hasMoreElements();) {
079                        Permission permission = (Permission) permissions.nextElement();
080                        policyConfiguration.addToRole(roleName, permission);
081    
082                    }
083                }
084            }
085    
086            if (principalRoleMapper != null) {
087                principalRoleMapper.install(contextIdToPermissionsMap.keySet());
088            }
089    
090            //link everything together
091            for (PolicyConfiguration policyConfiguration : contextIdToPolicyConfigurationMap.values()) {
092                for (PolicyConfiguration policyConfiguration2 : contextIdToPolicyConfigurationMap.values()) {
093                    if (policyConfiguration != policyConfiguration2) {
094                        policyConfiguration.linkConfiguration(policyConfiguration2);
095                    }
096                }
097            }
098    
099            //commit
100            for (PolicyConfiguration policyConfiguration : contextIdToPolicyConfigurationMap.values()) {
101                policyConfiguration.commit();
102            }
103    
104            //refresh policy
105            Policy policy = Policy.getPolicy();
106            policy.refresh();
107    
108            if (defaultSubjectInfo == null) {
109                defaultSubject = ContextManager.EMPTY;
110            } else {
111                defaultSubject = credentialStore.getSubject(defaultSubjectInfo.getRealm(), defaultSubjectInfo.getId());
112                registerSubject(defaultSubject);
113            }
114    
115            for (Map.Entry<String, SubjectInfo> entry : roleDesignates.entrySet()) {
116                String role = entry.getKey();
117                SubjectInfo subjectInfo = entry.getValue();
118                if (subjectInfo == null || credentialStore == null) {
119                    throw new NullPointerException("No subjectInfo for role " + role);
120                }
121                Subject roleDesignate = credentialStore.getSubject(subjectInfo.getRealm(), subjectInfo.getId());
122                registerSubject(roleDesignate);
123                this.roleDesignates.put(role, roleDesignate);
124            }
125        }
126    
127        private void registerSubject(Subject subject) {
128            ContextManager.registerSubject(subject);
129            SubjectId id = ContextManager.getSubjectId(subject);
130            subject.getPrincipals().add(new IdentificationPrincipal(id));
131        }
132    
133        public Subject getDefaultSubject() {
134            return defaultSubject;
135        }
136    
137        public Subject getSubjectForRole(String role) {
138            return roleDesignates.get(role);
139        }
140    
141        public void doStart() throws Exception {
142    
143        }
144    
145        public void doStop() throws Exception {
146            for (Map.Entry<String, Subject> entry : roleDesignates.entrySet()) {
147                Subject roleDesignate = entry.getValue();
148                ContextManager.unregisterSubject(roleDesignate);
149            }
150            if (defaultSubject != ContextManager.EMPTY) {
151                ContextManager.unregisterSubject(defaultSubject);
152            }
153    
154            if (principalRoleMapper != null) {
155                principalRoleMapper.uninstall(contextIdToPolicyConfigurationMap.keySet());
156            }
157    
158            for (PolicyConfiguration policyConfiguration : contextIdToPolicyConfigurationMap.values()) {
159                policyConfiguration.delete();
160            }
161        }
162    
163        public void doFail() {
164    
165        }
166    
167        public static final GBeanInfo GBEAN_INFO;
168    
169        static {
170            GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(ApplicationPolicyConfigurationManager.class, NameFactory.JACC_MANAGER);
171            infoBuilder.addAttribute("contextIdToPermissionsMap", Map.class, true);
172            infoBuilder.addAttribute("defaultSubjectInfo", SubjectInfo.class, true);
173            infoBuilder.addAttribute("roleDesignates", Map.class, true);
174            infoBuilder.addAttribute("classLoader", ClassLoader.class, false);
175            infoBuilder.addReference("CredentialStore", CredentialStore.class, NameFactory.GERONIMO_SERVICE);
176            infoBuilder.addReference("PrincipalRoleMapper", PrincipalRoleMapper.class, NameFactory.JACC_MANAGER);
177            infoBuilder.setConstructor(new String[] {"contextIdToPermissionsMap", "defaultSubjectInfo", "roleDesignates", "classLoader", "CredentialStore", "PrincipalRoleMapper"});
178            GBEAN_INFO = infoBuilder.getBeanInfo();
179        }
180    
181        public static GBeanInfo getGBeanInfo() {
182            return GBEAN_INFO;
183        }
184    }