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