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.jaas;
018    
019    import java.util.HashMap;
020    import java.util.List;
021    import java.util.Map;
022    import java.util.Set;
023    
024    import javax.security.auth.login.AppConfigurationEntry;
025    
026    import org.apache.geronimo.gbean.GBeanInfo;
027    import org.apache.geronimo.gbean.GBeanInfoBuilder;
028    import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
029    import org.apache.geronimo.kernel.Kernel;
030    import org.apache.geronimo.system.serverinfo.ServerInfo;
031    
032    
033    /**
034     * Holds a reference to a login module and the control flag.  A linked list of these forms the list of login modules
035     * in a GenericSecurityRealm.
036     *
037     * @version $Rev: 554977 $ $Date: 2007-07-10 11:32:56 -0400 (Tue, 10 Jul 2007) $
038     */
039    public class JaasLoginModuleUse implements JaasLoginModuleChain {
040        // See also http://java.sun.com/j2se/1.4.2/docs/guide/security/jaas/JAASLMDevGuide.html for more standard login module option keys
041        public final static String KERNEL_NAME_LM_OPTION = "org.apache.geronimo.security.realm.GenericSecurityRealm.KERNEL";
042        public final static String SERVERINFO_LM_OPTION = "org.apache.geronimo.security.realm.GenericSecurityRealm.SERVERINFO";
043        public final static String CLASSLOADER_LM_OPTION = "org.apache.geronimo.security.realm.GenericSecurityRealm.CLASSLOADER";
044    
045        private final LoginModuleSettings loginModule;
046        private final JaasLoginModuleUse next;
047        private LoginModuleControlFlag controlFlag;
048    
049        //for reference.
050        public JaasLoginModuleUse() {
051            loginModule = null;
052            next = null;
053            controlFlag = null;
054        }
055    
056        public JaasLoginModuleUse(LoginModuleSettings loginModule, JaasLoginModuleUse next, LoginModuleControlFlag controlFlag) {
057            this.loginModule = loginModule;
058            this.next = next;
059            this.controlFlag = controlFlag;
060        }
061    
062        public LoginModuleSettings getLoginModule() {
063            return loginModule;
064        }
065    
066        public JaasLoginModuleChain getNext() {
067            return next;
068        }
069    
070        public LoginModuleControlFlag getControlFlag() {
071            return controlFlag;
072        }
073    
074        public void setControlFlag(LoginModuleControlFlag controlFlag) {
075            this.controlFlag = controlFlag;
076        }
077    
078        public void configure(Set<String> domainNames, List<AppConfigurationEntry> loginModuleConfigurations, String realmName, Kernel kernel, ServerInfo serverInfo, ClassLoader classLoader) throws ClassNotFoundException {
079            Map<String, ?> suppliedOptions = loginModule.getOptions();
080            Map<String, Object> options;
081            if (suppliedOptions != null) {
082                options = new HashMap<String, Object>(suppliedOptions);
083            } else {
084                options = new HashMap<String, Object>();
085            }
086            if (kernel != null && !options.containsKey(KERNEL_NAME_LM_OPTION)) {
087                options.put(KERNEL_NAME_LM_OPTION, kernel.getKernelName());
088            }
089            if (serverInfo != null && !options.containsKey(SERVERINFO_LM_OPTION)) {
090                options.put(SERVERINFO_LM_OPTION, serverInfo);
091            }
092            if (!options.containsKey(CLASSLOADER_LM_OPTION)) {
093                options.put(CLASSLOADER_LM_OPTION, classLoader);
094            }
095            AppConfigurationEntry entry;
096            if (loginModule.isWrapPrincipals()) {
097                Class loginModuleClass;
098                loginModuleClass = classLoader.loadClass(loginModule.getLoginModuleClass());
099                options.put(WrappingLoginModule.CLASS_OPTION, loginModuleClass);
100                options.put(WrappingLoginModule.DOMAIN_OPTION, loginModule.getLoginDomainName());
101                options.put(WrappingLoginModule.REALM_OPTION, realmName);
102                entry = new AppConfigurationEntry(WrappingLoginModule.class.getName(), controlFlag.getFlag(), options);
103            } else {
104                entry = new AppConfigurationEntry(loginModule.getLoginModuleClass(), controlFlag.getFlag(), options);
105            }
106            if (loginModule.getLoginDomainName() != null) {
107                if (domainNames.contains(loginModule.getLoginDomainName())) {
108                    throw new IllegalStateException("Error in realm: one security realm cannot contain multiple login modules for the same login domain");
109                } else {
110                    domainNames.add(loginModule.getLoginDomainName());
111                }
112            }
113            loginModuleConfigurations.add(entry);
114    
115            if (next != null) {
116                next.configure(domainNames, loginModuleConfigurations, realmName, kernel, serverInfo, classLoader);
117            }
118        }
119    
120        public static final GBeanInfo GBEAN_INFO;
121    
122        static {
123            GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(JaasLoginModuleUse.class, "LoginModuleUse");
124            infoBuilder.addAttribute("controlFlag", LoginModuleControlFlag.class, true);
125            infoBuilder.addReference("LoginModule", LoginModuleSettings.class, NameFactory.LOGIN_MODULE);
126            infoBuilder.addReference("Next", JaasLoginModuleUse.class);
127    
128            infoBuilder.addInterface(JaasLoginModuleChain.class);
129            infoBuilder.setConstructor(new String[]{"LoginModule", "Next", "controlFlag"});
130            GBEAN_INFO = infoBuilder.getBeanInfo();
131        }
132    
133        public static GBeanInfo getGBeanInfo() {
134            return GBEAN_INFO;
135        }
136    }